<?xml version="1.0" encoding="utf-8" standalone="yes"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom">
  <channel>
    <title>Guides on Palmyra</title>
    <link>https://palmyra.dev/docs/guides/</link>
    <description>Recent content in Guides on Palmyra</description>
    <generator>Hugo</generator>
    <language>en-us</language>
    <atom:link href="https://palmyra.dev/docs/guides/index.xml" rel="self" type="application/rss+xml" />
    <item>
      <title>Security Configuration Recipes</title>
      <link>https://palmyra.dev/docs/guides/security-recipes/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://palmyra.dev/docs/guides/security-recipes/</guid>
      <description>&lt;h1 id=&#34;security-configuration-recipes&#34;&gt;Security Configuration Recipes&lt;a class=&#34;anchor&#34; href=&#34;#security-configuration-recipes&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;&#xA;&lt;p&gt;Palmyra doesn&amp;rsquo;t own your Spring Security setup — the user-management extension gives you an &lt;code&gt;AuthenticationProvider&lt;/code&gt;, but the filter chain is yours to compose. These are the four recipes every app ends up writing.&lt;/p&gt;&#xA;&lt;h2 id=&#34;1-session-based-login-for-a-spa&#34;&gt;1. Session-based login for a SPA&lt;a class=&#34;anchor&#34; href=&#34;#1-session-based-login-for-a-spa&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;The single-page-app default: &lt;code&gt;POST /auth/login&lt;/code&gt; establishes an HTTP session, a &lt;code&gt;JSESSIONID&lt;/code&gt; cookie authenticates subsequent requests, CSRF protects mutations, 401 on session expiry.&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-java&#34; data-lang=&#34;java&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;@Configuration&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;@EnableWebSecurity&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#a6e22e&#34;&gt;@RequiredArgsConstructor&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;class&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;SecurityConfig&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;private&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;final&lt;/span&gt; LocalDBAuthenticationProvider localDbProvider;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;@Bean&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; SecurityContextRepository &lt;span style=&#34;color:#a6e22e&#34;&gt;securityContextRepository&lt;/span&gt;() {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; DelegatingSecurityContextRepository(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; RequestAttributeSecurityContextRepository(),&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; HttpSessionSecurityContextRepository());&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;@Bean&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#66d9ef&#34;&gt;public&lt;/span&gt; SecurityFilterChain &lt;span style=&#34;color:#a6e22e&#34;&gt;filterChain&lt;/span&gt;(HttpSecurity http,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                                           SecurityContextRepository repo) &lt;span style=&#34;color:#66d9ef&#34;&gt;throws&lt;/span&gt; Exception {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        CsrfTokenRequestAttributeHandler csrfHandler &lt;span style=&#34;color:#f92672&#34;&gt;=&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; CsrfTokenRequestAttributeHandler();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        csrfHandler.&lt;span style=&#34;color:#a6e22e&#34;&gt;setCsrfRequestAttributeName&lt;/span&gt;(&lt;span style=&#34;color:#66d9ef&#34;&gt;null&lt;/span&gt;);   &lt;span style=&#34;color:#75715e&#34;&gt;// eager resolution — see §3&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#66d9ef&#34;&gt;return&lt;/span&gt; http&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .&lt;span style=&#34;color:#a6e22e&#34;&gt;authenticationProvider&lt;/span&gt;(localDbProvider)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .&lt;span style=&#34;color:#a6e22e&#34;&gt;securityContext&lt;/span&gt;(c &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; c.&lt;span style=&#34;color:#a6e22e&#34;&gt;securityContextRepository&lt;/span&gt;(repo))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .&lt;span style=&#34;color:#a6e22e&#34;&gt;sessionManagement&lt;/span&gt;(s &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; s.&lt;span style=&#34;color:#a6e22e&#34;&gt;sessionCreationPolicy&lt;/span&gt;(SessionCreationPolicy.&lt;span style=&#34;color:#a6e22e&#34;&gt;IF_REQUIRED&lt;/span&gt;))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .&lt;span style=&#34;color:#a6e22e&#34;&gt;csrf&lt;/span&gt;(c &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; c&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        .&lt;span style=&#34;color:#a6e22e&#34;&gt;csrfTokenRepository&lt;/span&gt;(CookieCsrfTokenRepository.&lt;span style=&#34;color:#a6e22e&#34;&gt;withHttpOnlyFalse&lt;/span&gt;())&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        .&lt;span style=&#34;color:#a6e22e&#34;&gt;csrfTokenRequestHandler&lt;/span&gt;(csrfHandler)&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        .&lt;span style=&#34;color:#a6e22e&#34;&gt;ignoringRequestMatchers&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/auth/login&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/auth/logout&amp;#34;&lt;/span&gt;))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .&lt;span style=&#34;color:#a6e22e&#34;&gt;authorizeHttpRequests&lt;/span&gt;(a &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; a&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        .&lt;span style=&#34;color:#a6e22e&#34;&gt;requestMatchers&lt;/span&gt;(&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/auth/login&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/auth/logout&amp;#34;&lt;/span&gt;, &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;/public/**&amp;#34;&lt;/span&gt;).&lt;span style=&#34;color:#a6e22e&#34;&gt;permitAll&lt;/span&gt;()&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        .&lt;span style=&#34;color:#a6e22e&#34;&gt;anyRequest&lt;/span&gt;().&lt;span style=&#34;color:#a6e22e&#34;&gt;authenticated&lt;/span&gt;())&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .&lt;span style=&#34;color:#a6e22e&#34;&gt;exceptionHandling&lt;/span&gt;(e &lt;span style=&#34;color:#f92672&#34;&gt;-&amp;gt;&lt;/span&gt; e.&lt;span style=&#34;color:#a6e22e&#34;&gt;authenticationEntryPoint&lt;/span&gt;(&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                        &lt;span style=&#34;color:#66d9ef&#34;&gt;new&lt;/span&gt; HttpStatusEntryPoint(HttpStatus.&lt;span style=&#34;color:#a6e22e&#34;&gt;UNAUTHORIZED&lt;/span&gt;)))&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;                .&lt;span style=&#34;color:#a6e22e&#34;&gt;build&lt;/span&gt;();&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Pair it with an idle timeout in &lt;code&gt;application.yml&lt;/code&gt;:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Programmatic Access</title>
      <link>https://palmyra.dev/docs/guides/programmatic-access/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://palmyra.dev/docs/guides/programmatic-access/</guid>
      <description>&lt;h1 id=&#34;programmatic-access--api-keys-for-non-browser-clients&#34;&gt;Programmatic Access — API keys for non-browser clients&lt;a class=&#34;anchor&#34; href=&#34;#programmatic-access--api-keys-for-non-browser-clients&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;&#xA;&lt;p&gt;&lt;code&gt;palmyra-dbpwd-mgmt&lt;/code&gt; covers username/password for people. Python scripts, batch jobs, and headless agents need a different credential: an API key that can be provisioned per client, revoked independently, and audited. This guide shows how to add that as a second &lt;code&gt;AuthenticationProvider&lt;/code&gt; alongside your user chain so both land on the same ACL model.&lt;/p&gt;&#xA;&lt;h2 id=&#34;the-design-in-one-diagram&#34;&gt;The design in one diagram&lt;a class=&#34;anchor&#34; href=&#34;#the-design-in-one-diagram&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt;┌──────────────────────┐&#xA;│  Client — browser    │ ─── POST /auth/login (user/pass) ─► session cookie&#xA;│                      │ ─── subsequent calls with JSESSIONID&#xA;└──────────────────────┘                    │&#xA;                                            │  both resolve to&#xA;┌──────────────────────┐                    │  xpm_user.login_name&#xA;│  Client — script     │                    │  → same @Permission evaluator&#xA;│  (Python/Java/curl)  │ ── X-Api-Key: ... ─┤&#xA;└──────────────────────┘                    │&#xA;                                            ▼&#xA;                                    handler with @Permission(&amp;#34;X&amp;#34;, ...)&#xA;                                    → PalmyraPermissionEvaluator&#xA;                                    → xpm_acl_group_permission row&lt;/code&gt;&lt;/pre&gt;&lt;p&gt;One principal model, two ways to authenticate.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Dev Bootstrap &amp; Seed Data</title>
      <link>https://palmyra.dev/docs/guides/dev-bootstrap-seeding/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://palmyra.dev/docs/guides/dev-bootstrap-seeding/</guid>
      <description>&lt;h1 id=&#34;dev-bootstrap--seed-data&#34;&gt;Dev Bootstrap &amp;amp; Seed Data&lt;a class=&#34;anchor&#34; href=&#34;#dev-bootstrap--seed-data&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;&#xA;&lt;p&gt;Palmyra reads the DB schema at startup — so every new dev environment needs the same tables, constraints, and seed rows before the first request goes through. This guide covers the three problems every project hits:&lt;/p&gt;&#xA;&lt;ol&gt;&#xA;&lt;li&gt;DDL that belongs in version control but isn&amp;rsquo;t managed by Hibernate.&lt;/li&gt;&#xA;&lt;li&gt;Seed rows for lookup tables and an admin user.&lt;/li&gt;&#xA;&lt;li&gt;Order-of-operations with Hibernate&amp;rsquo;s &lt;code&gt;ddl-auto&lt;/code&gt;.&lt;/li&gt;&#xA;&lt;/ol&gt;&#xA;&lt;h2 id=&#34;1-ddl-auto--what-to-set-and-why&#34;&gt;1. &lt;code&gt;ddl-auto&lt;/code&gt; — what to set, and why&lt;a class=&#34;anchor&#34; href=&#34;#1-ddl-auto--what-to-set-and-why&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Profile&lt;/th&gt;&#xA;          &lt;th&gt;Setting&lt;/th&gt;&#xA;          &lt;th&gt;Reasoning&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Dev against a stable schema&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;ddl-auto: none&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Palmyra reads metadata at startup; ddl-auto re-diffing churns the schema and has fought with our &lt;code&gt;DevBootstrap&lt;/code&gt;-managed columns in practice&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Dev, actively evolving the schema&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;ddl-auto: update&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Fast iteration; JPA entity changes show up in the DB. Accept the churn&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Test (testcontainers / H2)&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;ddl-auto: create-drop&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Throw-away&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;&lt;strong&gt;Prod&lt;/strong&gt;&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;ddl-auto: validate&lt;/code&gt;&lt;/td&gt;&#xA;          &lt;td&gt;Fail fast on schema drift&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;p&gt;Our working recommendation: &lt;strong&gt;start with &lt;code&gt;update&lt;/code&gt; in dev, flip to &lt;code&gt;none&lt;/code&gt; once your schema stabilises&lt;/strong&gt; — at that point DevBootstrap owns the DDL deltas and Hibernate stops interfering.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Dynamic Navigation</title>
      <link>https://palmyra.dev/docs/guides/dynamic-navigation/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://palmyra.dev/docs/guides/dynamic-navigation/</guid>
      <description>&lt;h1 id=&#34;dynamic-navigation--data-driven-sidebar&#34;&gt;Dynamic Navigation — data-driven sidebar&lt;a class=&#34;anchor&#34; href=&#34;#dynamic-navigation--data-driven-sidebar&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;&#xA;&lt;p&gt;Most admin apps want a side nav that&amp;rsquo;s (a) driven by data, not hard-coded, and (b) filtered per-user by ACL grants. &lt;code&gt;palmyra-dbacl-mgmt&lt;/code&gt; gives you the backend half (two tables + one endpoint); &lt;code&gt;@palmyralabs/template-tribble&lt;/code&gt; gives you the frontend half (&lt;code&gt;DynamicMenu&lt;/code&gt;). This guide stitches them together.&lt;/p&gt;&#xA;&lt;h2 id=&#34;architecture&#34;&gt;Architecture&lt;a class=&#34;anchor&#34; href=&#34;#architecture&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;pre tabindex=&#34;0&#34;&gt;&lt;code&gt; xpm_menu  ─── parent/child tree of nav entries (id, name, code, display_label, path, …)&#xA;     │&#xA;     │  M:N via xpm_acl_menu (menu_id × group_id × mask)&#xA;     │&#xA; xpm_group ── xpm_acl_user ── xpm_user&#xA;                                  │&#xA;                                  │  current logged-in user&#xA;                                  ▼&#xA;          GET /acl/menu/listAll  →  rows the user&amp;#39;s groups have mask &amp;gt; 0 on&#xA;                                  │&#xA;                                  ▼&#xA;          React: useTreestore + DynamicMenu (AsyncTreeMenu under the hood)&lt;/code&gt;&lt;/pre&gt;&lt;h2 id=&#34;1-the-tables&#34;&gt;1. The tables&lt;a class=&#34;anchor&#34; href=&#34;#1-the-tables&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Both ship as JPA entities inside &lt;code&gt;palmyra-dbacl-mgmt&lt;/code&gt; — Hibernate creates them with &lt;code&gt;ddl-auto: update&lt;/code&gt;:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Schema Discovery (internals)</title>
      <link>https://palmyra.dev/docs/guides/schema-discovery/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://palmyra.dev/docs/guides/schema-discovery/</guid>
      <description>&lt;h1 id=&#34;schema-discovery--how-palmyra-reads-your-database&#34;&gt;Schema Discovery — how Palmyra reads your database&lt;a class=&#34;anchor&#34; href=&#34;#schema-discovery--how-palmyra-reads-your-database&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;&#xA;&lt;p&gt;The &lt;a href=&#34;https://palmyra.dev/docs/intro/mental-model/&#34;&gt;Mental Model&lt;/a&gt; page says &amp;ldquo;the database schema is the source of truth.&amp;rdquo; This page is the under-the-hood version — what Palmyra actually reads, when, and how that drives request-time behaviour. Useful when debugging why a field doesn&amp;rsquo;t resolve or why a join looks different from what you expect.&lt;/p&gt;&#xA;&lt;h2 id=&#34;what-gets-read-and-when&#34;&gt;What gets read, and when&lt;a class=&#34;anchor&#34; href=&#34;#what-gets-read-and-when&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;At Spring context startup, Palmyra builds an in-memory &lt;code&gt;Schema&lt;/code&gt; object backed by a &lt;code&gt;SchemaProvider&lt;/code&gt;. The default &lt;code&gt;SchemaProvider&lt;/code&gt; reads:&lt;/p&gt;</description>
    </item>
    <item>
      <title>Performance &amp; Observability</title>
      <link>https://palmyra.dev/docs/guides/performance-observability/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://palmyra.dev/docs/guides/performance-observability/</guid>
      <description>&lt;h1 id=&#34;performance--observability&#34;&gt;Performance &amp;amp; Observability&lt;a class=&#34;anchor&#34; href=&#34;#performance--observability&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;&#xA;&lt;p&gt;Palmyra is raw JDBC — no Hibernate session, no lazy loading, no dirty-check sweep. The claim on the home page is &amp;ldquo;sub-50 ms typical&amp;rdquo;; this page covers what you have to do to keep it that way, and what to measure when you don&amp;rsquo;t.&lt;/p&gt;&#xA;&lt;h2 id=&#34;1-pagination-defaults&#34;&gt;1. Pagination defaults&lt;a class=&#34;anchor&#34; href=&#34;#1-pagination-defaults&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;p&gt;Every &lt;code&gt;QueryHandler&lt;/code&gt; response is paginated. Defaults from &lt;code&gt;application.yml&lt;/code&gt;:&lt;/p&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-yaml&#34; data-lang=&#34;yaml&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;palmyra&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;query&lt;/span&gt;:&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;default-limit&lt;/span&gt;: &lt;span style=&#34;color:#ae81ff&#34;&gt;15&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;max-limit&lt;/span&gt;:     &lt;span style=&#34;color:#ae81ff&#34;&gt;500&lt;/span&gt;&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;Client overrides come via query params: &lt;code&gt;?limit=30&amp;amp;offset=60&lt;/code&gt;. Clients that don&amp;rsquo;t send &lt;code&gt;limit&lt;/code&gt; get &lt;code&gt;default-limit&lt;/code&gt;. Clients that send &lt;code&gt;limit &amp;gt; max-limit&lt;/code&gt; get truncated to &lt;code&gt;max-limit&lt;/code&gt; — no error, just capped. Set &lt;code&gt;max-limit&lt;/code&gt; conservatively — it&amp;rsquo;s your guard against accidental full-table dumps.&lt;/p&gt;</description>
    </item>
    <item>
      <title>Frontend Project Setup</title>
      <link>https://palmyra.dev/docs/guides/frontend-project-setup/</link>
      <pubDate>Mon, 01 Jan 0001 00:00:00 +0000</pubDate>
      <guid>https://palmyra.dev/docs/guides/frontend-project-setup/</guid>
      <description>&lt;h1 id=&#34;frontend-project-setup--deep-walkthrough&#34;&gt;Frontend project setup — deep walkthrough&lt;a class=&#34;anchor&#34; href=&#34;#frontend-project-setup--deep-walkthrough&#34;&gt;#&lt;/a&gt;&lt;/h1&gt;&#xA;&lt;p&gt;&lt;a href=&#34;https://palmyra.dev/docs/tutorial/frontend/&#34;&gt;&lt;code&gt;tutorial/frontend/01-setup.md&lt;/code&gt;&lt;/a&gt; covers the three-command start. This page is the fuller version — the files you actually need, how they fit together, and what to configure before you build your first grid.&lt;/p&gt;&#xA;&lt;h2 id=&#34;1-stack&#34;&gt;1. Stack&lt;a class=&#34;anchor&#34; href=&#34;#1-stack&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;table&gt;&#xA;  &lt;thead&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;th&gt;Concern&lt;/th&gt;&#xA;          &lt;th&gt;Choice&lt;/th&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/thead&gt;&#xA;  &lt;tbody&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Build&lt;/td&gt;&#xA;          &lt;td&gt;Vite 7+ with &lt;code&gt;@vitejs/plugin-react&lt;/code&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Language&lt;/td&gt;&#xA;          &lt;td&gt;TypeScript 5.9+&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Runtime&lt;/td&gt;&#xA;          &lt;td&gt;React 19 + react-dom 19&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;UI kit&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;@mantine/core&lt;/code&gt;, &lt;code&gt;@mantine/dates&lt;/code&gt;, &lt;code&gt;@mantine/hooks&lt;/code&gt; (v8) &lt;em&gt;— or the MUI variants&lt;/em&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Data layer&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;@palmyralabs/palmyra-wire&lt;/code&gt; — store factory (single source of network truth)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Forms&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;@palmyralabs/rt-forms&lt;/code&gt; + &lt;code&gt;@palmyralabs/rt-forms-mantine&lt;/code&gt; (or &lt;code&gt;-mui&lt;/code&gt;)&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Grid / form templates&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;@palmyralabs/template-tribble&lt;/code&gt; — &lt;code&gt;SummaryGrid&lt;/code&gt;, &lt;code&gt;DialogNewForm&lt;/code&gt;, &lt;code&gt;DialogEditForm&lt;/code&gt;, &lt;code&gt;DynamicMenu&lt;/code&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Router&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;react-router-dom&lt;/code&gt; v7&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Notifications&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;react-toastify&lt;/code&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;HTTP&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;axios&lt;/code&gt; (for interceptors); palmyra-wire uses it under the hood&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;      &lt;tr&gt;&#xA;          &lt;td&gt;Utilities&lt;/td&gt;&#xA;          &lt;td&gt;&lt;code&gt;@palmyralabs/ts-utils&lt;/code&gt;, &lt;code&gt;dayjs&lt;/code&gt;&lt;/td&gt;&#xA;      &lt;/tr&gt;&#xA;  &lt;/tbody&gt;&#xA;&lt;/table&gt;&#xA;&lt;h2 id=&#34;2-packagejson--minimum-deps&#34;&gt;2. &lt;code&gt;package.json&lt;/code&gt; — minimum deps&lt;a class=&#34;anchor&#34; href=&#34;#2-packagejson--minimum-deps&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-json&#34; data-lang=&#34;json&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;{&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;name&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;my-web&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;version&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;0.1.0&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;type&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;module&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;scripts&amp;#34;&lt;/span&gt;: {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;dev&amp;#34;&lt;/span&gt;:   &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;vite&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;build&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;tsc -b &amp;amp;&amp;amp; vite build&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;lint&amp;#34;&lt;/span&gt;:  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;eslint .&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;dependencies&amp;#34;&lt;/span&gt;: {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;@mantine/core&amp;#34;&lt;/span&gt;:                   &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;^8.3.1&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;@mantine/dates&amp;#34;&lt;/span&gt;:                  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;^8.3.1&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;@mantine/hooks&amp;#34;&lt;/span&gt;:                  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;^8.3.1&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;@palmyralabs/palmyra-wire&amp;#34;&lt;/span&gt;:       &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;^1.2.0&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;@palmyralabs/rt-forms&amp;#34;&lt;/span&gt;:           &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;github:palmyralabs/rt-forms&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;@palmyralabs/rt-forms-mantine&amp;#34;&lt;/span&gt;:   &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;github:palmyralabs/rt-forms-mantine&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;@palmyralabs/template-tribble&amp;#34;&lt;/span&gt;:   &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;github:palmyralabs/rt-template-tribble&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;@palmyralabs/ts-utils&amp;#34;&lt;/span&gt;:           &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;^0.3.0&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;axios&amp;#34;&lt;/span&gt;:                           &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;^1.12.2&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;dayjs&amp;#34;&lt;/span&gt;:                           &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;^1.11.18&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;react&amp;#34;&lt;/span&gt;:                           &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;^19.1.1&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;react-dom&amp;#34;&lt;/span&gt;:                       &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;^19.1.1&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;react-icons&amp;#34;&lt;/span&gt;:                     &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;^5.5.0&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;react-router-dom&amp;#34;&lt;/span&gt;:                &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;^7.9.1&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;react-toastify&amp;#34;&lt;/span&gt;:                  &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;^11.0.5&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;devDependencies&amp;#34;&lt;/span&gt;: {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;@types/react&amp;#34;&lt;/span&gt;:        &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;^19.1.13&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;@types/react-dom&amp;#34;&lt;/span&gt;:    &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;^19.1.9&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;@vitejs/plugin-react&amp;#34;&lt;/span&gt;:&lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;^5.0.3&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;typescript&amp;#34;&lt;/span&gt;:          &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;~5.9.2&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;vite&amp;#34;&lt;/span&gt;:                &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;^7.1.6&amp;#34;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#f92672&#34;&gt;&amp;#34;vite-tsconfig-paths&amp;#34;&lt;/span&gt;: &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#34;^5.1.4&amp;#34;&lt;/span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  }&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;}&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;h2 id=&#34;3-viteconfigts&#34;&gt;3. &lt;code&gt;vite.config.ts&lt;/code&gt;&lt;a class=&#34;anchor&#34; href=&#34;#3-viteconfigts&#34;&gt;#&lt;/a&gt;&lt;/h2&gt;&#xA;&lt;div class=&#34;highlight&#34;&gt;&lt;pre tabindex=&#34;0&#34; style=&#34;color:#f8f8f2;background-color:#272822;-moz-tab-size:4;-o-tab-size:4;tab-size:4;-webkit-text-size-adjust:none;&#34;&gt;&lt;code class=&#34;language-ts&#34; data-lang=&#34;ts&#34;&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;import&lt;/span&gt; { &lt;span style=&#34;color:#a6e22e&#34;&gt;defineConfig&lt;/span&gt; } &lt;span style=&#34;color:#66d9ef&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;vite&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;react&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;@vitejs/plugin-react&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;import&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;tsconfigPaths&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;from&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;vite-tsconfig-paths&amp;#39;&lt;/span&gt;;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;&lt;span style=&#34;color:#66d9ef&#34;&gt;export&lt;/span&gt; &lt;span style=&#34;color:#66d9ef&#34;&gt;default&lt;/span&gt; &lt;span style=&#34;color:#a6e22e&#34;&gt;defineConfig&lt;/span&gt;({&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;plugins&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; [&lt;span style=&#34;color:#a6e22e&#34;&gt;react&lt;/span&gt;(), &lt;span style=&#34;color:#a6e22e&#34;&gt;tsconfigPaths&lt;/span&gt;()],&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  &lt;span style=&#34;color:#a6e22e&#34;&gt;server&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;port&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;3000&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;open&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/app/login&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    &lt;span style=&#34;color:#a6e22e&#34;&gt;proxy&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;/api&amp;#39;&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; {&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;target&lt;/span&gt;&lt;span style=&#34;color:#f92672&#34;&gt;:&lt;/span&gt; &lt;span style=&#34;color:#e6db74&#34;&gt;&amp;#39;http://localhost:6060&amp;#39;&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;changeOrigin&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;        &lt;span style=&#34;color:#a6e22e&#34;&gt;secure&lt;/span&gt;: &lt;span style=&#34;color:#66d9ef&#34;&gt;false&lt;/span&gt;,&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;      },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;    },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;  },&#xA;&lt;/span&gt;&lt;/span&gt;&lt;span style=&#34;display:flex;&#34;&gt;&lt;span&gt;});&lt;/span&gt;&lt;/span&gt;&lt;/code&gt;&lt;/pre&gt;&lt;/div&gt;&lt;p&gt;The proxy is critical — forwards &lt;code&gt;/api/**&lt;/code&gt; to the Spring Boot service so &lt;code&gt;withCredentials&lt;/code&gt; cookies stay same-origin from the browser&amp;rsquo;s perspective. Without this, CSRF / session won&amp;rsquo;t round-trip in dev.&lt;/p&gt;</description>
    </item>
  </channel>
</rss>
