<?xml version="1.0" encoding="utf-8" standalone="yes"?><rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom"><channel><title>LTI on Pauls Blog</title><link>https://prule.github.io/pauls-blog/tags/lti/</link><description>Recent content in LTI on Pauls Blog</description><generator>Hugo</generator><language>en-us</language><lastBuildDate>Fri, 15 May 2026 00:00:00 +1000</lastBuildDate><atom:link href="https://prule.github.io/pauls-blog/tags/lti/index.xml" rel="self" type="application/rss+xml"/><item><title>The Repository That Doesn't Grow: Criteria over Finder Methods</title><link>https://prule.github.io/pauls-blog/post/coding/2026/anatomy-of-repository/</link><pubDate>Fri, 15 May 2026 00:00:00 +1000</pubDate><guid>https://prule.github.io/pauls-blog/post/coding/2026/anatomy-of-repository/</guid><description>&lt;h1 id="the-repository-that-doesnt-grow-criteria-over-finder-methods"&gt;The Repository That Doesn&amp;rsquo;t Grow: Criteria over Finder Methods&lt;/h1&gt;
&lt;p&gt;&lt;code&gt;SessionRepository&lt;/code&gt; in the Laptime Insights server is ~130 lines and exposes seven public methods. It has served every read path the app needs — listing, single lookup, filter discovery, time-bucketed aggregation, and the writes — without growing a new finder method for each new screen. This post is a tour of how it&amp;rsquo;s structured and why the method surface stays small.&lt;/p&gt;</description></item><item><title>Building an ACC Dashboard with AI-Assisted Development</title><link>https://prule.github.io/pauls-blog/post/coding/2026/ai-assisted-development-1/</link><pubDate>Thu, 14 May 2026 00:00:00 +1000</pubDate><guid>https://prule.github.io/pauls-blog/post/coding/2026/ai-assisted-development-1/</guid><description>&lt;p&gt;Building useful software is the best way to learn. Building useful software &lt;em&gt;for a problem you actually have&lt;/em&gt; is even better.&lt;/p&gt;
&lt;p&gt;I race in Assetto Corsa Competizione. I wanted a proper dashboard for analysing lap times. So I started building one.&lt;/p&gt;
&lt;h2 id="the-real-goal"&gt;The Real Goal&lt;/h2&gt;
&lt;p&gt;Two goals, really. First: something genuinely useful. Second: a vehicle for practising software development - and increasingly, for understanding how AI tools fit into a real workflow.&lt;/p&gt;</description></item><item><title>Anatomy of a Search Endpoint: Filter, Sort, Paginate, HATEOAS</title><link>https://prule.github.io/pauls-blog/post/coding/2026/anatomy-of-search/</link><pubDate>Mon, 11 May 2026 00:00:00 +1000</pubDate><guid>https://prule.github.io/pauls-blog/post/coding/2026/anatomy-of-search/</guid><description>&lt;h1 id="anatomy-of-a-search-endpoint-filter-sort-paginate-hateoas"&gt;Anatomy of a Search Endpoint: Filter, Sort, Paginate, HATEOAS&lt;/h1&gt;
&lt;p&gt;A walk through &lt;code&gt;GET /api/1/sessions&lt;/code&gt; in the Laptime Insights server — from the Ktor route, down through the use case and persistence port, into the Exposed query, and back out as a HATEOAS page that the React frontend uses to render a sortable table.&lt;/p&gt;
&lt;p&gt;The feature is small but it touches every layer, so it&amp;rsquo;s a good example of how clean architecture lets each concern live in exactly one place: the domain decides what&amp;rsquo;s sortable, the repository decides how that maps to a column, the resource decides how it appears on the wire, and the UI decides how to render it. Nothing leaks.&lt;/p&gt;</description></item></channel></rss>