<?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: jreeeedd</title>
    <description>The latest articles on DEV Community by jreeeedd (@jreeeedd).</description>
    <link>https://dev.to/jreeeedd</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.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F465625%2Fa81c0bad-ce7e-4c4b-8a7d-11389f570e15.png</url>
      <title>DEV Community: jreeeedd</title>
      <link>https://dev.to/jreeeedd</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://dev.to/feed/jreeeedd"/>
    <language>en</language>
    <item>
      <title>Otimizando a perfomance do Schepta com React</title>
      <dc:creator>jreeeedd</dc:creator>
      <pubDate>Thu, 16 Apr 2026 22:04:16 +0000</pubDate>
      <link>https://dev.to/jreeeedd/otimizando-a-perfomance-do-schepta-com-react-2k7h</link>
      <guid>https://dev.to/jreeeedd/otimizando-a-perfomance-do-schepta-com-react-2k7h</guid>
      <description>&lt;p&gt;Quando você cria um formulário com dezenas de campos, cada digitação do usuário não deveria custar mais do que alguns microssegundos de trabalho do JavaScript mas na maioria das bibliotecas de formulário, uma única tecla pressionada causa uma cascata de re-renders que percorre toda a árvore React — do componente raiz até os filhos.&lt;/p&gt;

&lt;p&gt;Esse artigo documenta as otimizações que fizemos no Schepta para eliminar esse problema com algumas mudanças arquiteturais que mudam fundamentalmente &lt;em&gt;onde&lt;/em&gt; o estado vive e &lt;em&gt;quem&lt;/em&gt; é notificado quando ele muda.&lt;/p&gt;




&lt;h2&gt;
  
  
  O problema: onde o estado mora importa
&lt;/h2&gt;

&lt;p&gt;Num formulário típico construído com &lt;code&gt;useState&lt;/code&gt;, o estado de todos os campos vive num único objeto no topo da árvore:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;FormFactory (state: { nome, email, telefone, ... })
  └── ScheptaFormProvider (context: { values, adapter })
        └── Context.Provider  ← emite novo valor a cada keystroke
              └── Seção A
                    └── Campo "nome"    ← re-renderiza (faz sentido)
                    └── Campo "email"   ← re-renderiza (não precisa)
              └── Seção B
                    └── Campo "telefone" ← re-renderiza (não precisa)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;strong&gt;O React Context não é granular.&lt;/strong&gt; Quando qualquer valor no contexto muda, todos os consumidores daquele contexto re-renderizam (mesmo que o campo específico não tenha mudado).&lt;/p&gt;




&lt;h2&gt;
  
  
  A solução em três camadas
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Camada 1 — O adapter não depende mais do React para escrever
&lt;/h3&gt;

&lt;p&gt;Antes, quando o usuário digitava algo, o &lt;code&gt;NativeReactFormAdapter&lt;/code&gt; chamava &lt;code&gt;this.setState&lt;/code&gt; — o setter do &lt;code&gt;useState&lt;/code&gt; do &lt;code&gt;FormFactory&lt;/code&gt;. Isso colocava o React no caminho crítico de toda escrita:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight javascript"&gt;&lt;code&gt;&lt;span class="nf"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;nome&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;João&lt;/span&gt;&lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;
  &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;setState&lt;/span&gt;&lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="na"&gt;nome&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="dl"&gt;"&lt;/span&gt;&lt;span class="s2"&gt;João&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="err"&gt;←&lt;/span&gt; &lt;span class="nx"&gt;React&lt;/span&gt; &lt;span class="nx"&gt;setState&lt;/span&gt;
  &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="nx"&gt;FormFactory&lt;/span&gt; &lt;span class="nx"&gt;re&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;renderiza&lt;/span&gt;
  &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="nx"&gt;ScheptaFormProvider&lt;/span&gt; &lt;span class="nx"&gt;re&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;renderiza&lt;/span&gt;
  &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="nx"&gt;Context&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;Provider&lt;/span&gt; &lt;span class="nx"&gt;emite&lt;/span&gt; &lt;span class="nx"&gt;novo&lt;/span&gt; &lt;span class="nx"&gt;valor&lt;/span&gt;
  &lt;span class="err"&gt;→&lt;/span&gt; &lt;span class="nx"&gt;TODOS&lt;/span&gt; &lt;span class="nx"&gt;os&lt;/span&gt; &lt;span class="nx"&gt;campos&lt;/span&gt; &lt;span class="nx"&gt;re&lt;/span&gt;&lt;span class="o"&gt;-&lt;/span&gt;&lt;span class="nx"&gt;renderizam&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;A mudança: o adapter agora é &lt;strong&gt;self-contained&lt;/strong&gt;. O estado vive em &lt;code&gt;this.state&lt;/code&gt; (JS puro), e as escritas notificam diretamente os subscribers via um sistema de pub/sub interno, sem passar pelo React:&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="nf"&gt;setValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;field&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="nx"&gt;value&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;any&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="k"&gt;void&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
  &lt;span class="c1"&gt;// Atualiza estado interno (JS síncrono, sem React)&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&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="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;state&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;field&lt;/span&gt;&lt;span class="p"&gt;]:&lt;/span&gt; &lt;span class="nx"&gt;value&lt;/span&gt; &lt;span class="p"&gt;};&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_version&lt;/span&gt;&lt;span class="o"&gt;++&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;

  &lt;span class="c1"&gt;// Notifica só quem precisa saber&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_fieldSubscribers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;get&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;field&lt;/span&gt;&lt;span class="p"&gt;)?.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cb&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;cb&lt;/span&gt;&lt;span class="p"&gt;());&lt;/span&gt;
  &lt;span class="k"&gt;this&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nx"&gt;_globalSubscribers&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;forEach&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;cb&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nf"&gt;cb&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;O adapter ganhou também um método &lt;code&gt;setValues&lt;/code&gt; para resets e hidratação externa, que notifica todos os subscribers de uma vez.&lt;/p&gt;




&lt;h3&gt;
  
  
  Camada 2 — O contexto React se torna estável
&lt;/h3&gt;

&lt;p&gt;Com o adapter self-contained, não há mais razão para passar &lt;code&gt;values&lt;/code&gt; pelo contexto. O contexto agora carrega apenas uma coisa: &lt;strong&gt;a referência estável do adapter&lt;/strong&gt;. E essa referência nunca muda após o mount.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Antes: contexto mudava a cada keystroke&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;contextValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMemo&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;adapter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;adapter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;values&lt;/span&gt;&lt;span class="p"&gt;]);&lt;/span&gt;

&lt;span class="c1"&gt;// Depois: contexto nunca muda&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;contextValue&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMemo&lt;/span&gt;&lt;span class="p"&gt;(()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;({&lt;/span&gt; &lt;span class="nx"&gt;adapter&lt;/span&gt; &lt;span class="p"&gt;}),&lt;/span&gt; &lt;span class="p"&gt;[]);&lt;/span&gt; &lt;span class="c1"&gt;// deps vazias&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Com isso, &lt;code&gt;useContext(ScheptaFormContext)&lt;/code&gt; deixa de disparar re-renders. O React não tem mais nada novo para propagar.&lt;/p&gt;

&lt;p&gt;Para que os campos ainda recebam seus valores de forma reativa, usamos &lt;code&gt;useSyncExternalStore&lt;/code&gt; — que conecta diretamente ao pub/sub do adapter, sem passar pelo contexto:&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;function&lt;/span&gt; &lt;span class="nf"&gt;useScheptaFieldValue&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;field&lt;/span&gt;&lt;span class="p"&gt;:&lt;/span&gt; &lt;span class="kr"&gt;string&lt;/span&gt;&lt;span class="p"&gt;):&lt;/span&gt; &lt;span class="kr"&gt;any&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;adapter&lt;/span&gt; &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useContext&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;ScheptaFormContext&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt; &lt;span class="c1"&gt;// stable, never re-renders&lt;/span&gt;

  &lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;subscribe&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;onStoreChange&lt;/span&gt;&lt;span class="p"&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="k"&gt;void&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;adapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribeField&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;field&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;onStoreChange&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;adapter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;field&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;getSnapshot&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
    &lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="nx"&gt;adapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;getFieldSnapshot&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;field&lt;/span&gt;&lt;span class="p"&gt;),&lt;/span&gt;
    &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;adapter&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;field&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="nf"&gt;useSyncExternalStore&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;subscribe&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;getSnapshot&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;getSnapshot&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;useSyncExternalStore&lt;/code&gt; é a API do React 18 projetada exatamente para esse padrão: stores externos que gerenciam seu próprio estado. Ela garante que só o campo cujo valor mudou re-renderiza, e nenhum outro.&lt;/p&gt;




&lt;h3&gt;
  
  
  Camada 3 — O FormFactory só re-renderiza quando precisa
&lt;/h3&gt;

&lt;p&gt;Num formulário sem templates dinâmicos, o &lt;code&gt;FormFactory&lt;/code&gt; não precisa saber &lt;em&gt;nada&lt;/em&gt; sobre o que o usuário está digitando. Ele renderizou a estrutura do formulário uma vez e seu trabalho está feito.&lt;/p&gt;

&lt;p&gt;Mas o Schepta suporta expressões como &lt;code&gt;{{ $formValues.tipo === 'pj' }}&lt;/code&gt; para mostrar/esconder campos condicionalmente. Nesses casos, o &lt;code&gt;FormFactory&lt;/code&gt; precisa re-rodar o orchestrator quando os valores mudam.&lt;/p&gt;

&lt;p&gt;A solução: detectar isso &lt;strong&gt;em tempo de configuração&lt;/strong&gt;, não em tempo de execução.&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight typescript"&gt;&lt;code&gt;&lt;span class="c1"&gt;// Checagem estática feita uma vez por schema (useMemo([schema]))&lt;/span&gt;
&lt;span class="kd"&gt;const&lt;/span&gt; &lt;span class="nx"&gt;needsFormValueRerender&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useMemo&lt;/span&gt;&lt;span class="p"&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;hasFormValueTemplates&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="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="p"&gt;);&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;&lt;code&gt;hasFormValueTemplates&lt;/code&gt; percorre o schema recursivamente e retorna &lt;code&gt;true&lt;/code&gt; se encontrar qualquer &lt;code&gt;{{ ... }}&lt;/code&gt; que referencie &lt;code&gt;$formValues&lt;/code&gt;. Para formulários que só usam &lt;code&gt;$externalContext&lt;/code&gt; ou não têm templates, retorna &lt;code&gt;false&lt;/code&gt;.&lt;/p&gt;

&lt;p&gt;Com isso, o &lt;code&gt;FormFactory&lt;/code&gt; só se inscreve no adapter se o schema realmente precisar:&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;subscribeToAdapter&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="nf"&gt;useCallback&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;
  &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;onStoreChange&lt;/span&gt;&lt;span class="p"&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="k"&gt;void&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt; &lt;span class="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
    &lt;span class="k"&gt;if &lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;needsFormValueRerender&lt;/span&gt; &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; &lt;span class="nx"&gt;adapter&lt;/span&gt; &lt;span class="k"&gt;instanceof&lt;/span&gt; &lt;span class="nx"&gt;NativeReactFormAdapter&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;adapter&lt;/span&gt;&lt;span class="p"&gt;.&lt;/span&gt;&lt;span class="nf"&gt;subscribeAll&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="nx"&gt;onStoreChange&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="o"&gt;=&amp;gt;&lt;/span&gt; &lt;span class="p"&gt;{};&lt;/span&gt; &lt;span class="c1"&gt;// no-op para formulários estáticos&lt;/span&gt;
  &lt;span class="p"&gt;},&lt;/span&gt;
  &lt;span class="p"&gt;[&lt;/span&gt;&lt;span class="nx"&gt;needsFormValueRerender&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="nx"&gt;adapter&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;h2&gt;
  
  
  O resultado no Profiler
&lt;/h2&gt;

&lt;h3&gt;
  
  
  Antes
&lt;/h3&gt;

&lt;p&gt;Ao digitar em qualquer campo, o React Profiler mostrava:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;code&gt;FormFactory&lt;/code&gt; como origem do update&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;ScheptaFormProvider&lt;/code&gt; re-renderizando por consequência&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;Context.Provider&lt;/code&gt; emitindo novo valor&lt;/li&gt;
&lt;li&gt;Todos os &lt;code&gt;DefaultFieldRenderer&lt;/code&gt; na árvore re-renderizando&lt;/li&gt;
&lt;/ul&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.amazonaws.com%2Fuploads%2Farticles%2F747i9e20x2o4b4kldk93.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.amazonaws.com%2Fuploads%2Farticles%2F747i9e20x2o4b4kldk93.png" alt=" " width="800" height="314"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;h3&gt;
  
  
  Depois
&lt;/h3&gt;

&lt;p&gt;O mesmo keystroke no Profiler mostra apenas:&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;O &lt;code&gt;DefaultFieldRenderer&lt;/code&gt; específico daquele campo re-renderizando&lt;/li&gt;
&lt;li&gt;
&lt;code&gt;FormFactory&lt;/code&gt; não aparece mais como origem de updates&lt;/li&gt;
&lt;li&gt;Todos os outros campos permanecem cinza (não re-renderizaram)&lt;/li&gt;
&lt;/ul&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.amazonaws.com%2Fuploads%2Farticles%2Fk0pssupcmi84aeh0r82h.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.amazonaws.com%2Fuploads%2Farticles%2Fk0pssupcmi84aeh0r82h.png" alt=" " width="800" height="187"&gt;&lt;/a&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Resumo das mudanças
&lt;/h2&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Antes&lt;/th&gt;
&lt;th&gt;Depois&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;setValue&lt;/code&gt; → &lt;code&gt;setState&lt;/code&gt; React → FormFactory re-renderiza&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;setValue&lt;/code&gt; → &lt;code&gt;this.state&lt;/code&gt; JS → só o campo re-renderiza&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Contexto carrega &lt;code&gt;{ adapter, values }&lt;/code&gt; — muda a cada keystroke&lt;/td&gt;
&lt;td&gt;Contexto carrega &lt;code&gt;{ adapter }&lt;/code&gt; — nunca muda&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Todos os &lt;code&gt;useContext()&lt;/code&gt; re-renderizam quando qualquer valor muda&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;useSyncExternalStore&lt;/code&gt; isola cada campo individualmente&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;FormFactory sempre re-renderiza em formulários com valores&lt;/td&gt;
&lt;td&gt;FormFactory re-renderiza &lt;strong&gt;somente&lt;/strong&gt; se o schema usa &lt;code&gt;{{ $formValues.* }}&lt;/code&gt;
&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;
&lt;code&gt;React.memo&lt;/code&gt; ineficaz (context cascade sobrepõe o memo)&lt;/td&gt;
&lt;td&gt;
&lt;code&gt;React.memo&lt;/code&gt; funciona como esperado — compara props, não cascata&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  O que não mudou
&lt;/h2&gt;

&lt;p&gt;A API pública do Schepta permanece idêntica. &lt;code&gt;FormFactory&lt;/code&gt;, &lt;code&gt;ScheptaFormProvider&lt;/code&gt;, &lt;code&gt;useScheptaFieldValue&lt;/code&gt;, &lt;code&gt;useScheptaFormValues&lt;/code&gt; — tudo funciona exatamente como antes. A otimização é transparente para quem usa a biblioteca.&lt;/p&gt;

&lt;p&gt;Formulários com templates dinâmicos como &lt;code&gt;{{ $formValues.tipo === 'pj' }}&lt;/code&gt; continuam funcionando corretamente: o &lt;code&gt;FormFactory&lt;/code&gt; detecta automaticamente que precisa acompanhar as mudanças de valor e se inscreve no adapter de forma seletiva.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>javascript</category>
      <category>performance</category>
      <category>react</category>
    </item>
    <item>
      <title>Onde e como usar o Schepta</title>
      <dc:creator>jreeeedd</dc:creator>
      <pubDate>Thu, 26 Mar 2026 16:20:19 +0000</pubDate>
      <link>https://dev.to/jreeeedd/onde-e-como-usar-o-schepta-308b</link>
      <guid>https://dev.to/jreeeedd/onde-e-como-usar-o-schepta-308b</guid>
      <description>&lt;p&gt;Este artigo é para quem vai adotar o Schepta: planos futuros da arquitetura (outras factories além de forms), cenários de uso — multi-tenant, testes A/B, wizards, white-label — e por que a suite de testes garante que sua aplicação pode focar na parte de negócio. No final, um resumo prático de onde o projeto vive e da extensibilidade.&lt;/p&gt;




&lt;h2&gt;
  
  
  Planos futuros e arquitetura: outras factories, prioridade em forms
&lt;/h2&gt;

&lt;p&gt;O core do Schepta (orquestrador, registry, middlewares, pipeline schema → render) é agnóstico do &lt;em&gt;tipo&lt;/em&gt; de UI. O mesmo mecanismo que hoje alimenta o &lt;strong&gt;FormFactory&lt;/strong&gt; pode alimentar outras factories — por exemplo &lt;strong&gt;MenuFactory&lt;/strong&gt; (navegação dinâmica a partir de schema), dashboards, wizards. A arquitetura já prevê isso (tipos de componente como &lt;code&gt;menu-item&lt;/code&gt;, &lt;code&gt;menu-container&lt;/code&gt; na documentação de conceitos).&lt;/p&gt;

&lt;p&gt;No momento foi priorizado forms porque &lt;strong&gt;grande parte da complexidade em aplicações multi-tenant está nos formulários&lt;/strong&gt;: campos por tenant, validações por contexto, fluxos diferentes por cliente. Resolver bem “schema → form” desbloqueia o cenário mais doloroso; outras factories podem vir em seguida.&lt;/p&gt;

&lt;p&gt;A arquitetura &lt;strong&gt;permite a criação de outras factories além de forms&lt;/strong&gt;. A escolha de lançar com foco em forms é priorização (multi-tenant + complexidade), não limitação do desenho.&lt;/p&gt;




&lt;h2&gt;
  
  
  Outros usos além de multi-tenant
&lt;/h2&gt;

&lt;p&gt;&lt;strong&gt;Multi-tenant&lt;/strong&gt; já está no centro: um schema por tenant, UI consistente.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Testes A/B:&lt;/strong&gt; o mesmo fluxo ou tela pode ser servido com schemas diferentes — por exemplo variação A com 3 campos, variação B com 5 campos ou ordem diferente. O backend ou a camada de feature flags entrega o schema da variação; o Schepta renderiza. Sem trocar código do app, só o JSON.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Wizards e fluxos dinâmicos:&lt;/strong&gt; próximos passos ou telas dependentes de contexto (respostas do usuário, perfil, permissões) podem ser modelados como schemas diferentes por etapa; o Schepta renderiza cada etapa.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;White-label / configuração por cliente:&lt;/strong&gt; além de multi-tenant “duro”, cenários em que cada cliente tem sua própria definição de formulários (CRM, ferramentas internas); o schema vem de configuração ou API e o Schepta mantém a UI consistente.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Prototipagem e ferramentas low-code:&lt;/strong&gt; ferramentas que geram ou editam schemas (por humano ou por IA) e usam o Schepta como runtime de preview ou produção.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Uso com IA e produtos no chat:&lt;/strong&gt; um produto que roda diretamente dentro do chat (por exemplo via MCP — Model Context Protocol) mantém a consistência entre os componentes: o cliente cria o próprio MCP e disponibiliza nas tools o schema de acordo com o usuário e com o que ele está pedindo; o Schepta renderiza o formulário ou a UI no próprio chat. Assim, assistentes como o Claude podem invocar as tools (obter schema, validar, abrir preview) e a interface exibida é sempre a mesma engine Schepta, previsível e testável.&lt;/p&gt;

&lt;p&gt;Schema-driven UI serve para vários problemas, não só “um form por tenant”.&lt;/p&gt;

&lt;div class="table-wrapper-paragraph"&gt;&lt;table&gt;
&lt;thead&gt;
&lt;tr&gt;
&lt;th&gt;Cenário&lt;/th&gt;
&lt;th&gt;Como o Schepta ajuda&lt;/th&gt;
&lt;/tr&gt;
&lt;/thead&gt;
&lt;tbody&gt;
&lt;tr&gt;
&lt;td&gt;Multi-tenant&lt;/td&gt;
&lt;td&gt;Um schema por tenant; mesma engine, UI consistente.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Testes A/B&lt;/td&gt;
&lt;td&gt;Schemas diferentes por variação; sem alterar código.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Wizards&lt;/td&gt;
&lt;td&gt;Um schema por etapa; renderização por contexto.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;White-label&lt;/td&gt;
&lt;td&gt;Schema por cliente via config ou API.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;Low-code / IA&lt;/td&gt;
&lt;td&gt;Runtime estável para schemas gerados ou editados.&lt;/td&gt;
&lt;/tr&gt;
&lt;tr&gt;
&lt;td&gt;IA / produto no chat&lt;/td&gt;
&lt;td&gt;Cliente expõe schema nas tools do MCP; Schepta renderiza no chat com a mesma engine.&lt;/td&gt;
&lt;/tr&gt;
&lt;/tbody&gt;
&lt;/table&gt;&lt;/div&gt;




&lt;h2&gt;
  
  
  Testes como garantia: o app foca no negócio
&lt;/h2&gt;

&lt;p&gt;O Schepta é coberto por &lt;strong&gt;103 testes unitários&lt;/strong&gt; e &lt;strong&gt;26 testes E2E&lt;/strong&gt; (Playwright) que validam o fluxo completo: schema → resolução → render → interação em React, Vue e Vanilla, incluindo integrações com react-hook-form e Formik. Isso &lt;strong&gt;garante que a engine se comporta corretamente&lt;/strong&gt; — resolução de componentes, middlewares, validação, binding de campos.&lt;/p&gt;

&lt;p&gt;Ao adotar o Schepta, o time do app &lt;strong&gt;não precisa se preocupar&lt;/strong&gt; com “será que o schema vira componente certo?”, “será que o middleware roda na ordem?”, “será que o form adapter conecta?”. Esses detalhes estão cobertos pela suite; regressões da engine são detectadas antes de chegar ao app.&lt;/p&gt;

&lt;p&gt;Nos aplicativos que usam o Schepta, o time pode concentrar esforço na &lt;strong&gt;parte voltada para negócio&lt;/strong&gt;: validações específicas do domínio, regras de negócio em middlewares, definições de forms por contexto ou tenant, integração com APIs e fluxos. A “infraestrutura” de schema→UI está testada e estável.&lt;/p&gt;

&lt;p&gt;Os testes são a &lt;strong&gt;garantia de que as funcionalidades da engine funcionam&lt;/strong&gt;, abstraindo esses detalhes para que, nos apps onde o Schepta será usado, as preocupações sejam &lt;strong&gt;apenas a parte voltada para negócio&lt;/strong&gt; (validações específicas, definições específicas de forms, etc.).&lt;/p&gt;




&lt;h2&gt;
  
  
  Em resumo
&lt;/h2&gt;

&lt;ul&gt;
&lt;li&gt;
&lt;strong&gt;Onde vive:&lt;/strong&gt; monorepo com &lt;code&gt;@schepta/core&lt;/code&gt;, adapters (react, vue, vanilla), factories por framework; documentação e exemplos em &lt;a href="https://schepta.org" rel="noopener noreferrer"&gt;schepta.org&lt;/a&gt;.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Testes:&lt;/strong&gt; 103 testes unitários e 26 testes E2E (React, Vue, Vanilla), incluindo react-hook-form e Formik — garantia da engine; o app foca em lógica de negócio.&lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;Extensibilidade:&lt;/strong&gt; middlewares para transformar props; registry para trocar componentes; renderers por tipo (field, container, button, content); expressões em props com &lt;code&gt;$formValues&lt;/code&gt; e &lt;code&gt;$externalContext&lt;/code&gt;.&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;Showcases por framework (React, Vue, Vanilla, MUI, Chakra, Vuetify, etc.) estão disponíveis na documentação.&lt;/p&gt;




&lt;h2&gt;
  
  
  Próximo passo
&lt;/h2&gt;

&lt;p&gt;No último artigo da série entramos em &lt;a href="//05-como-o-schepta-funciona-por-dentro.md"&gt;&lt;strong&gt;como o Schepta funciona por dentro&lt;/strong&gt;&lt;/a&gt;: factories, orquestradores, component registry e o pipeline de resolução até o render. Para quem quer profundidade técnica.&lt;/p&gt;

&lt;p&gt;Enquanto isso: &lt;a href="https://schepta.org" rel="noopener noreferrer"&gt;schepta.org&lt;/a&gt; para docs e exemplos.&lt;/p&gt;

</description>
      <category>architecture</category>
      <category>frontend</category>
      <category>tooling</category>
      <category>ui</category>
    </item>
    <item>
      <title>Why I didn't take the common path</title>
      <dc:creator>jreeeedd</dc:creator>
      <pubDate>Sat, 14 Mar 2026 16:26:00 +0000</pubDate>
      <link>https://dev.to/jreeeedd/why-i-didnt-take-the-common-path-2o8l</link>
      <guid>https://dev.to/jreeeedd/why-i-didnt-take-the-common-path-2o8l</guid>
      <description>&lt;p&gt;The current moment in software development is pushing many devs toward two paths: microsaas (or a closed product) to monetize quickly, or betting on AI agents and agentic automation — products and tools where the agent "resolves" tasks on its own. This article is about why I didn't go that route. An analysis of the landscape, a conscious choice, and a provocation: the common path is legitimate, but it's not the only one.&lt;/p&gt;




&lt;h2&gt;
  
  
  What's at stake
&lt;/h2&gt;

&lt;p&gt;There's pressure for revenue, for visible impact, for surfing the wave of the moment. Microsaas has become a shortcut for many indie developers: lean product, subscription, growth. On the other side, AI agents and agentic workflows have gained traction — the idea that AI isn't just an assistant, but an autonomous workforce that reads code, implements features, opens PRs. In 2025–2026 this stopped being just an experiment and became a concrete option for both product and positioning.&lt;/p&gt;

&lt;p&gt;None of this is wrong. These are choices. What I want to make clear is: &lt;strong&gt;why, in the case of Schepta, I chose a different path.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Foundation before agent, value before price
&lt;/h2&gt;

&lt;p&gt;At some point you've probably seen the same thing I have: devs launching microsaas, others automating everything with agents, the feeling that anyone not on that track is leaving money on the table.&lt;/p&gt;

&lt;p&gt;I considered both paths.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;Microsaas brings contracts, pricing, and vendor lock-in before the value is proven. For a problem like this — turning a schema into real UI, stably across multiple frameworks — that's friction before its time. The value needs to be demonstrated first; the business model comes after.&lt;/li&gt;
&lt;li&gt;Agents have a similar appeal: automating interface generation seems like the obvious next step. But agents that generate or modify UI need a stable foundation to operate on — a clear, auditable contract between backend, agent, and frontend. Building the agent before that foundation is fragile. Order matters: first the engine works well, then the agent has something solid to build on.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;But a stable foundation has a cost: it needs to be proven. Broken forms and flows impact users and business directly — it's a mission-critical problem. Schepta's 100+ unit and E2E tests exist exactly for this reason: so the engine is reliable enough to be extended, contributed to, and used in production without surprises.&lt;/p&gt;

&lt;p&gt;And that was the path I chose. Whether it was the right one, only time will tell.&lt;/p&gt;

&lt;p&gt;If this discussion about paths resonated with you, Schepta's documentation and examples are waiting for you at &lt;a href="https://schepta.org" rel="noopener noreferrer"&gt;schepta.org&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;What about you: are you on the microsaas path, the agents path, or building something else entirely? What drove your decision?&lt;/p&gt;




&lt;h2&gt;
  
  
  Next step
&lt;/h2&gt;

&lt;p&gt;In the next article in the series we talk about &lt;strong&gt;When AI generates the interface: the schema as a guardrail&lt;/strong&gt;: how the ecosystem (json-render, A2UI) validates this approach, how Schepta responds to the problem of AI non-determinism, and how it fits into workflows ranging from assisted coding to 100% automated agents.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>programming</category>
      <category>ai</category>
      <category>productivity</category>
    </item>
    <item>
      <title>What Schepta is and what problem it solves</title>
      <dc:creator>jreeeedd</dc:creator>
      <pubDate>Sat, 14 Mar 2026 15:10:27 +0000</pubDate>
      <link>https://dev.to/jreeeedd/what-schepta-is-and-what-problem-it-solves-42l9</link>
      <guid>https://dev.to/jreeeedd/what-schepta-is-and-what-problem-it-solves-42l9</guid>
      <description>&lt;p&gt;This article explains what Schepta is, the problem it solves, and the space it fills. Why I chose an open source library over a microsaas — and why I haven't (yet) bet on AI agents that resolve tasks autonomously — is the topic of the &lt;strong&gt;next article&lt;/strong&gt; in the series.&lt;/p&gt;




&lt;h2&gt;
  
  
  What it is and what problem it solves
&lt;/h2&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.amazonaws.com%2Fuploads%2Farticles%2Fmywzbwcgv8e82daa4920.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.amazonaws.com%2Fuploads%2Farticles%2Fmywzbwcgv8e82daa4920.png" alt="Before vs After" width="800" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Schepta&lt;/strong&gt; is a tool that turns an interface description — in JSON format — into real screens and forms, without having to write each screen by hand in code. That description can be interpreted in React, Vue, or plain JavaScript, depending on the project.&lt;/p&gt;

&lt;p&gt;The &lt;strong&gt;problem&lt;/strong&gt; it helps solve shows up when the interface depends on many contexts: multiple clients (multi-tenant), multiple flows, A/B tests, or when the backend — or even AI tools — define what should appear on screen. In those cases, writing and maintaining each variation in code becomes chaos. Schepta centralizes the screen definition in a single format (the schema); a single engine interprets that format and generates the interface. Those using Schepta can focus on business rules and on defining what to show in each context, instead of the implementation details of each variation.&lt;/p&gt;




&lt;h2&gt;
  
  
  Why Schepta exists — the space it fills
&lt;/h2&gt;

&lt;p&gt;Schepta exists for scenarios where you need the &lt;strong&gt;interface definition&lt;/strong&gt; (what to show, in what order, with what validations) to be treated as data — a schema that carries UI semantics, not just data validation. It was designed to be &lt;strong&gt;framework-agnostic&lt;/strong&gt;: the same schema works in React, Vue, or plain JavaScript. The core is lean and extensible, with sensible defaults you can swap out when needed. And the entire flow was built for &lt;strong&gt;server-driven or context-driven UI&lt;/strong&gt; — for example, one schema per client or per tenant — not just for fixed forms defined at build time.&lt;/p&gt;

&lt;p&gt;If this space makes sense for your project, Schepta is an option. The choice between Schepta and other tools depends on the needs of each project and team; what matters is that this space exists and that Schepta is here to fill it.&lt;/p&gt;

&lt;p&gt;If this problem sounds familiar, the guide, documentation, and examples (React, Vue, and Vanilla) are at &lt;a href="https://schepta.org" rel="noopener noreferrer"&gt;schepta.org&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;Have you ever dealt with this chaos of forms that change per client, A/B test, or backend? How did you solve it?&lt;/p&gt;




&lt;h2&gt;
  
  
  Next step
&lt;/h2&gt;

&lt;p&gt;In the next article in the series I talk about &lt;strong&gt;why I didn't take the common path&lt;/strong&gt;: an analysis of the current moment in software development, what many devs are doing (microsaas, AI agents, and agentic automation) — and why I chose an open source library, without SaaS and without betting (yet) on agents that resolve tasks autonomously.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>ai</category>
      <category>opensource</category>
      <category>ui</category>
    </item>
    <item>
      <title>Quando a IA gera a interface: o schema como guardrail</title>
      <dc:creator>jreeeedd</dc:creator>
      <pubDate>Fri, 13 Mar 2026 22:28:37 +0000</pubDate>
      <link>https://dev.to/jreeeedd/quando-a-ia-gera-a-interface-o-schema-como-guardrail-2acd</link>
      <guid>https://dev.to/jreeeedd/quando-a-ia-gera-a-interface-o-schema-como-guardrail-2acd</guid>
      <description>&lt;h1&gt;
  
  
  Schepta no mundo das IAs
&lt;/h1&gt;

&lt;p&gt;Grandes players na corrida de IA e de plataformas já adotam a ideia de “UI a partir de JSON” ou protocolos declarativos. O Schepta não está inventando o conceito; está implementando uma engine framework-agnostic no mesmo espaço. Neste artigo: como essa tendência valida o caminho, como o Schepta responde ao problema do não-determinismo das IAs e como ele se encaixa em fluxos que vão do código assistido ao 100% automatizado com agents.&lt;/p&gt;




&lt;h2&gt;
  
  
  Validação: json-render e o ecossistema
&lt;/h2&gt;

&lt;p&gt;A ideia de usar schema ou JSON como fonte da verdade para a interface já é levada a sério por quem constrói ferramentas de desenvolvimento. Projetos como o &lt;strong&gt;json-render&lt;/strong&gt; (Vercel) focam em renderizar UI a partir de JSON no ecossistema React. O &lt;strong&gt;A2UI&lt;/strong&gt; (Google) é um projeto aberto para interfaces dirigidas por agentes: um único spec em JSON pode ser renderizado em várias plataformas (web, Flutter, etc.). Isso reforça que o caminho do Schepta — especificação declarativa, múltiplos runtimes — está alinhado com a direção do mercado.&lt;/p&gt;

&lt;p&gt;O Schepta implementa uma engine com foco em forms e extensibilidade (middlewares, registry), no mesmo espaço conceitual em que esses projetos atuam. A citação aqui é de validação: o caminho é válido.&lt;/p&gt;




&lt;h2&gt;
  
  
  Schepta como resposta ao não-determinismo das IAs
&lt;/h2&gt;

&lt;p&gt;IAs são não determinísticas. A mesma pergunta pode gerar saídas diferentes; código ou UI gerados diretamente por LLMs variam em formato, estilo e até correção. Colocar isso direto na tela ou no código da aplicação gera imprevisibilidade e risco.&lt;/p&gt;

&lt;p&gt;O Schepta introduz uma &lt;strong&gt;camada de contrato&lt;/strong&gt;. Em vez de a IA gerar componentes ou markup solto, ela gera — ou o desenvolvedor edita — um &lt;strong&gt;schema JSON&lt;/strong&gt;. Esse schema é validado (estrutura, tipos, regras) e só então é transformado em UI pelo motor do Schepta. Ou seja: &lt;strong&gt;dado um schema válido, a UI é determinística&lt;/strong&gt;. A não-determinismo fica contida na produção ou edição do schema; a renderização é sempre previsível e testável.&lt;/p&gt;

&lt;p&gt;Em fluxos com IA — copilot, agents, backends que montam UI dinamicamente — você precisa de um ponto de estabilidade. O schema é esse ponto: pode ser gerado por IA, por humano ou por um agent; uma vez válido, o Schepta garante o mesmo resultado. Testes E2E podem rodar sobre schemas fixos; regressões vêm de mudanças no schema, não de variação aleatória do render.&lt;/p&gt;

&lt;p&gt;Em resumo: o Schepta é a camada que torna a UI previsível mesmo quando a fonte (IA, agent, backend) não é.&lt;/p&gt;




&lt;h2&gt;
  
  
  Fluxos de trabalho com IA: do código assistido ao 100% automatizado
&lt;/h2&gt;

&lt;p&gt;O Schepta se posiciona em um contínuo de fluxos com IA.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Código assistido (human-in-the-loop):&lt;/strong&gt; o desenvolvedor usa IA para sugerir ou gerar schemas (por exemplo: “gera um form de cadastro com email, nome, aceite de termos”); revisa e ajusta o JSON; o Schepta renderiza. A IA acelera a produção do schema; o humano valida; a engine garante UI consistente.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Híbrido (IA gera, humano aprova):&lt;/strong&gt; o backend ou uma ferramenta alimentada por IA produz o schema (formulário por tenant, wizard por contexto); um passo de aprovação ou validação — humano ou por regras — pode existir antes de enviar ao front; o Schepta recebe o schema e renderiza. Ainda há controle; a renderização continua determinística.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;100% automatizado (agents):&lt;/strong&gt; um agent toma decisões e produz o schema (por exemplo um assistente que monta a tela conforme a conversa); o schema é enviado ao cliente; o Schepta renderiza sem intervenção humana. O contrato (schema) segue válido e versionável; o único não-determinismo está na geração do schema pelo agent; uma vez entregue, a UI é previsível e auditável.&lt;/p&gt;

&lt;p&gt;Em todos os níveis, o Schepta oferece: &lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;
&lt;strong&gt;interface estável&lt;/strong&gt; — sempre schema in, UI out; &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;validação na entrada&lt;/strong&gt; — schema inválido não vira tela quebrada; 3. &lt;strong&gt;mesma engine&lt;/strong&gt; para assistido e automatizado, permitindo evoluir o fluxo sem trocar de stack; &lt;/li&gt;
&lt;li&gt;
&lt;strong&gt;testabilidade&lt;/strong&gt; — cenários com schemas fixos cobrem o comportamento do render independentemente de quem gerou o schema.&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Do código assistido ao 100% automatizado com agents, o Schepta é a camada que transforma qualquer schema válido em UI determinística — seja o schema escrito à mão, sugerido por um copilot ou gerado por um agent. Já existe um exemplo concreto desse fluxo: o &lt;strong&gt;MCP do Schepta no Claude&lt;/strong&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Demo: Schepta via MCP no Claude
&lt;/h2&gt;

&lt;p&gt;O &lt;strong&gt;MCP (Model Context Protocol)&lt;/strong&gt; permite que assistentes como o Claude usem ferramentas externas. Existe um MCP para o Schepta que expõe três ferramentas no Claude: obter o JSON Schema dos formulários, validar uma instância de formulário contra esse schema e abrir um &lt;em&gt;preview&lt;/em&gt; do formulário diretamente no chat. Assim, você pode pedir ao Claude que crie ou edite um formulário Schepta em linguagem natural; o Claude chama as ferramentas (schema → validação → preview) e o formulário é renderizado na conversa.&lt;/p&gt;

&lt;p&gt;Um exemplo de prompt que você pode usar para reproduzir a demonstração:&lt;/p&gt;

&lt;blockquote&gt;
&lt;p&gt;Crie um formulário de cadastro de funcionário usando o MCP do Schepta. O formulário deve ter as seções e campos abaixo:&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Seção "Dados Pessoais"&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Nome completo (InputText)&lt;/li&gt;
&lt;li&gt;E-mail corporativo (InputText)&lt;/li&gt;
&lt;li&gt;Telefone (InputPhone)&lt;/li&gt;
&lt;/ul&gt;

&lt;p&gt;&lt;strong&gt;Seção "Cargo e Departamento"&lt;/strong&gt;&lt;/p&gt;

&lt;ul&gt;
&lt;li&gt;Cargo (InputText)&lt;/li&gt;
&lt;li&gt;Departamento (InputSelect)&lt;/li&gt;
&lt;li&gt;Data de início (InputDate)&lt;/li&gt;
&lt;/ul&gt;
&lt;/blockquote&gt;

&lt;p&gt;Configuração e descrição das ferramentas: &lt;a href="https://dev.to/pt-BR/guide/schepta-mcp"&gt;Schepta MCP na documentação&lt;/a&gt;.&lt;/p&gt;




&lt;h2&gt;
  
  
  Próximo passo
&lt;/h2&gt;

&lt;p&gt;No próximo artigo da série falamos de &lt;strong&gt;onde e como usar o Schepta&lt;/strong&gt;: planos futuros (outras factories além de forms), outros usos (multi-tenant, testes A/B, wizards, white-label).&lt;/p&gt;

</description>
      <category>agents</category>
      <category>ai</category>
      <category>frontend</category>
      <category>ui</category>
    </item>
    <item>
      <title>Por que não fui pelo caminho comum</title>
      <dc:creator>jreeeedd</dc:creator>
      <pubDate>Fri, 13 Mar 2026 19:09:08 +0000</pubDate>
      <link>https://dev.to/jreeeedd/por-que-nao-fui-pelo-caminho-comum-56fn</link>
      <guid>https://dev.to/jreeeedd/por-que-nao-fui-pelo-caminho-comum-56fn</guid>
      <description>&lt;p&gt;O momento atual no desenvolvimento de software empurra muitos devs para dois caminhos: microsaas (ou produto fechado) para monetizar rápido, ou apostar em agentes de IA e automação com agentes — produtos e ferramentas em que o agente “resolve” tarefas sozinho. Este artigo é sobre por que não fui por aí. Uma análise do cenário, uma escolha consciente e uma provocação: o caminho comum é legítimo, mas não é o único.&lt;/p&gt;




&lt;h2&gt;
  
  
  O que está em jogo
&lt;/h2&gt;

&lt;p&gt;Há pressão por receita, por impacto visível e surfar a onda da vez. Microsaas virou atalho para muitos indies: produto enxuto, assinatura, crescimento. Do outro lado, agentes de IA e workflows agentic ganharam tração — a ideia de que a IA não é só assistente, mas workforce autônoma que lê código, implementa features, abre PRs. Em 2025–2026 isso deixou de ser só experimento e virou opção concreta de produto e de posicionamento.&lt;/p&gt;

&lt;p&gt;Nada disso é errado. São escolhas. O que quero deixar claro é: &lt;strong&gt;por que, no caso do Schepta, escolhi outro caminho.&lt;/strong&gt;&lt;/p&gt;




&lt;h2&gt;
  
  
  Base antes de agente, valor antes de preço
&lt;/h2&gt;

&lt;p&gt;Em algum momento você provavelmente viu o mesmo que eu: devs lançando microsaas, outros automatizando tudo com agents, a sensação de que quem não está nessa trilha está deixando dinheiro na mesa.&lt;/p&gt;

&lt;p&gt;Eu considerei os dois caminhos.&lt;/p&gt;

&lt;ol&gt;
&lt;li&gt;&lt;p&gt;Microsaas traz contrato, preço e vendor lock-in antes de o valor estar provado. Para um problema como esse — transformar um schema em UI real, de forma estável em vários frameworks — isso é fricção antes da hora. O valor precisa ser demonstrado primeiro; o modelo de negócio vem depois.&lt;/p&gt;&lt;/li&gt;
&lt;li&gt;&lt;p&gt;Agents têm um apelo parecido: automatizar a geração de interface parece o passo óbvio. Mas agents que geram ou alteram UI precisam de uma base estável para operar — um contrato claro e auditável entre backend, agent e frontend. Construir o agent antes dessa base é frágil. A ordem importa: primeiro a engine funciona bem, depois o agent tem onde se apoiar.&lt;/p&gt;&lt;/li&gt;
&lt;/ol&gt;

&lt;p&gt;Mas base estável tem um custo: precisa ser provada. Formulários e fluxos quebrados impactam usuário e negócio diretamente — é um problema mission critical. Os mais de 100 testes unitários e E2E do Schepta existem exatamente por isso: para que a engine seja confiável o suficiente para ser estendida, contribuída e usada em produção sem surpresas.&lt;/p&gt;

&lt;p&gt;E esse foi o caminho que eu escolhi, se foi o correto ou não, somente o tempo dirá.&lt;/p&gt;

&lt;p&gt;Se essa discussão de caminhos fez sentido pra você, a documentação e os exemplos do Schepta estão te esperando em &lt;a href="https://schepta.org" rel="noopener noreferrer"&gt;schepta.org&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;E você: está no caminho do microsaas, dos agentes ou tá construindo alguma outra coisa? Qual foi a linha que você seguiu pra tomada de decisão?&lt;/p&gt;




&lt;h2&gt;
  
  
  Próximo passo
&lt;/h2&gt;

&lt;p&gt;No próximo artigo da série falamos de &lt;strong&gt;Quando a IA gera a interface: o schema como guardrail&lt;/strong&gt;: como o ecossistema (json-render, A2UI) valida essa abordagem, como o Schepta responde ao problema do não-determinismo das IAs e como ele se encaixa em fluxos que vão do código assistido ao 100% automatizado com agents.&lt;/p&gt;

</description>
      <category>ai</category>
      <category>webdev</category>
      <category>agents</category>
      <category>opensource</category>
    </item>
    <item>
      <title>O que é o schepta e que problema ele resolve</title>
      <dc:creator>jreeeedd</dc:creator>
      <pubDate>Fri, 13 Mar 2026 15:39:44 +0000</pubDate>
      <link>https://dev.to/jreeeedd/o-que-e-o-schepta-e-que-problema-ele-resolve-3nl2</link>
      <guid>https://dev.to/jreeeedd/o-que-e-o-schepta-e-que-problema-ele-resolve-3nl2</guid>
      <description>&lt;p&gt;Este artigo explica o que é o Schepta, que problema ele resolve e que espaço ele preenche. Por que escolhi uma lib open source em vez de microsaas e por que não apostei (ainda) em agentes de IA que resolvem tarefas sozinhos é o tema do &lt;strong&gt;próximo artigo&lt;/strong&gt; da série.&lt;/p&gt;




&lt;h2&gt;
  
  
  O que é e que problema resolve
&lt;/h2&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.amazonaws.com%2Fuploads%2Farticles%2Ff97lx61wrefwph4h829z.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.amazonaws.com%2Fuploads%2Farticles%2Ff97lx61wrefwph4h829z.png" alt="Antes vs Depois do schepta" width="800" height="540"&gt;&lt;/a&gt;&lt;/p&gt;

&lt;p&gt;O &lt;strong&gt;Schepta&lt;/strong&gt; é uma ferramenta que transforma uma descrição da interface — em formato JSON — em telas e formulários reais, sem precisar escrever cada tela à mão em código. Essa descrição pode ser interpretada em React, Vue ou JavaScript puro, conforme o projeto.&lt;/p&gt;

&lt;p&gt;O &lt;strong&gt;problema&lt;/strong&gt; que ele ajuda a resolver aparece quando a interface depende de muitos contextos: vários clientes (multi-tenant), vários fluxos, testes A/B, ou quando o backend e até ferramentas de IA definem o que deve aparecer na tela. Nesses casos, escrever e manter cada variação em código vira caos. O Schepta centraliza a "definição" da tela num único formato (o schema); uma única engine interpreta esse formato e gera a interface. Quem usa o Schepta pode focar nas regras de negócio e na definição do que mostrar em cada contexto, em vez dos detalhes de implementação de cada variação.&lt;/p&gt;




&lt;h2&gt;
  
  
  Por que o Schepta existe — que espaço ele preenche
&lt;/h2&gt;

&lt;p&gt;O Schepta existe para cenários em que você precisa que a &lt;strong&gt;definição da interface&lt;/strong&gt; (o que mostrar, em que ordem, com que validações) seja tratada como dado — um schema que carrega semântica de UI, não só de validação de dados. Ele foi pensado para ser &lt;strong&gt;agnóstico de framework&lt;/strong&gt;: o mesmo schema pode ser usado em React, Vue ou JavaScript puro. O núcleo é enxuto e extensível, com padrões sensatos que você pode trocar quando precisar. E o fluxo todo foi desenhado para &lt;strong&gt;interface dirigida por servidor ou por contexto&lt;/strong&gt; — por exemplo um schema por cliente ou por tenant —, não só para formulários fixos definidos no momento do build.&lt;/p&gt;

&lt;p&gt;Se esse espaço faz sentido para o seu projeto, o Schepta é uma opção. A escolha entre usar o Schepta ou outras ferramentas depende das necessidades de cada projeto ou de cada time; o que importa é que esse espaço existe e que o Schepta está aí para preenchê-lo.&lt;/p&gt;

&lt;p&gt;Se esse problema te soa familiar, o guia, a documentação e os exemplos (React, Vue e Vanilla) estão em &lt;a href="https://schepta.org" rel="noopener noreferrer"&gt;schepta.org&lt;/a&gt;.&lt;/p&gt;

&lt;p&gt;E você: já passou por esse caos de forms que mudam por cliente, A/B ou backend? Como resolveu?&lt;/p&gt;




&lt;h2&gt;
  
  
  Próximo passo
&lt;/h2&gt;

&lt;p&gt;No próximo artigo da série conto &lt;strong&gt;por que não fui pelo caminho comum&lt;/strong&gt;: uma análise do momento atual no desenvolvimento de software, o que muitos devs estão fazendo (microsaas, agentes de IA e automação com agentes) e por que escolhi uma lib open source, sem SaaS e sem apostar (ainda) em agentes que resolvem tarefas sozinhos.&lt;/p&gt;

</description>
      <category>webdev</category>
      <category>opensource</category>
      <category>json</category>
      <category>ai</category>
    </item>
  </channel>
</rss>
