<?xml version="1.0" encoding="UTF-8"?><rss xmlns:dc="http://purl.org/dc/elements/1.1/" xmlns:content="http://purl.org/rss/1.0/modules/content/" xmlns:atom="http://www.w3.org/2005/Atom" version="2.0" xmlns:media="http://search.yahoo.com/mrss/"><channel><title><![CDATA[Taku Uechi]]></title><description><![CDATA[Learning by teaching.]]></description><link>https://takuu.me/</link><generator>Ghost 0.7</generator><lastBuildDate>Thu, 10 Sep 2026 03:43:59 GMT</lastBuildDate><atom:link href="https://takuu.me/rss/" rel="self" type="application/rss+xml"/><ttl>60</ttl><item><title><![CDATA[One Schema, Many Projections: Using Zod as the Canonical Model]]></title><description><![CDATA[<p>One pattern I've been using more lately is defining a model once and then treating everything else as a derivation or projection of that model.  This isn't necessarily a new idea, since we've been talking about a "single source of truth" forever, but I think it's become a lot more</p>]]></description><link>https://takuu.me/one-schema-many-projections-using-zod-as-the-canonical-model/</link><guid isPermaLink="false">bad8a3bb-3c0e-4d6c-a573-2217a8db5118</guid><dc:creator><![CDATA[Taku Uechi]]></dc:creator><pubDate>Fri, 21 Aug 2026 22:43:06 GMT</pubDate><content:encoded><![CDATA[<p>One pattern I've been using more lately is defining a model once and then treating everything else as a derivation or projection of that model.  This isn't necessarily a new idea, since we've been talking about a "single source of truth" forever, but I think it's become a lot more useful with TypeScript, shared packages, monorepos, code generation and now AI writing a much larger amount of application code.</p>

<p>The main idea is pretty simple.  Define the model once in the richest representation you have, then generate or derive everything else from it.  For TypeScript applications, I think Zod is a really good place to put that canonical definition because it gives you both runtime validation and static types from the same object.</p>

<h2 id="theproblemwithdefiningthesamemodeloverandover">The Problem With Defining the Same Model Over and Over</h2>

<p>A pretty normal application ends up defining the same thing several different ways.  You might start with a TypeScript interface:</p>

<pre><code class="language-ts">interface Player {  
  name: string;
  email: string;
  active?: boolean;
}
</code></pre>

<p>Then you have something similar in your database:</p>

<pre><code class="language-ts">const PlayerSchema = new Schema({  
  name: String,
  email: String,
  active: Boolean,
});
</code></pre>

<p>Then validation:</p>

<pre><code class="language-ts">const playerValidator = z.object({  
  name: z.string().min(1),
  email: z.string().email(),
  active: z.boolean().optional(),
});
</code></pre>

<p>Then your frontend form has another definition, the API documentation describes the same fields again and maybe your tests have some factory that also knows what a valid Player is.  None of these are necessarily wrong, but you now have several different things that are supposed to represent the same model.</p>

<p>Eventually somebody updates one and forgets another.  Maybe the frontend says a field is optional while the API says it's required, or TypeScript says something is valid but your runtime validator rejects it.  The problem isn't really writing the code, it's keeping all of these definitions synchronized.</p>

<h2 id="makingzodthecanonicalschema">Making Zod the Canonical Schema</h2>

<p>A simplified Player schema could look like this:</p>

<pre><code class="language-ts">import { z } from 'zod';

export const PlayerSchema = z.object({  
  id: z.string(),
  name: z.string().min(1),
  email: z.string().email(),
  teamId: z.string(),
  active: z.boolean().optional(),
});

export type Player = z.infer&lt;typeof PlayerSchema&gt;;  
</code></pre>

<p>Right away the TypeScript interface goes away because the type is derived directly from the schema:</p>

<pre><code class="language-ts">type Player = z.infer&lt;typeof PlayerSchema&gt;;  
</code></pre>

<p>At the same time, you also have runtime validation:</p>

<pre><code class="language-ts">PlayerSchema.parse(data);  
</code></pre>

<p>That by itself is already useful, but I think the more interesting part is continuing this idea further.  Instead of only generating the TypeScript type, the Zod schema becomes the canonical representation and everything else becomes a projection of it.</p>

<pre><code class="language-text">                    ┌─ TypeScript types
                    │
                    ├─ API validation
                    │
Zod canonical ──────┼─ Forms  
schema              │  
+ metadata          ├─ Database models
                    │
                    ├─ OpenAPI
                    │
                    ├─ Documentation
                    │
                    ├─ Test fixtures
                    │
                    └─ AI schemas
</code></pre>

<p>Some of these projections are basically free and some require a little bit of code generation, but the important part is that they all start from the same place.</p>

<h2 id="sharingthesameschemaonthefrontendandbackend">Sharing the Same Schema on the Frontend and Backend</h2>

<p>This gets especially useful in a monorepo.  You can put the canonical schema in a shared package and both the frontend and backend import it.</p>

<pre><code class="language-text">packages/  
  schemas/
    player.ts
</code></pre>

<p>Then both sides can use:</p>

<pre><code class="language-ts">import {  
  PlayerSchema,
  type Player,
} from '@staty/schemas';
</code></pre>

<p>The API knows what a Player is, the frontend knows what a Player is and a form can use the exact same validation rules.  Instead of keeping the frontend and backend "in sync", they are actually using the same object.</p>

<p>For example, React Hook Form can use the same schema directly:</p>

<pre><code class="language-ts">useForm({  
  resolver: zodResolver(PlayerSchema),
});
</code></pre>

<p>Or if a form only uses part of a model, you can derive another schema from it:</p>

<pre><code class="language-ts">const EditPlayerSchema = PlayerSchema.pick({  
  name: true,
  email: true,
});
</code></pre>

<p>I like this a lot more than creating something like <code>EditPlayerFormValidator</code>, <code>EditPlayerDTO</code> and <code>EditPlayerType</code> separately and hoping they continue to match six months from now.</p>

<h2 id="parseattheapiboundary">Parse at the API Boundary</h2>

<p>Another part of this pattern is parsing input at the API boundary instead of trusting it.  This is something TypeScript by itself doesn't really solve.</p>

<p>This:</p>

<pre><code class="language-ts">const player = req.body as Player;  
</code></pre>

<p>doesn't validate anything.  It basically just tells TypeScript to trust you.</p>

<p>Instead:</p>

<pre><code class="language-ts">const result = PlayerSchema.safeParse(req.body);

if (!result.success) {  
  return res.status(400).json(result.error);
}

const player = result.data;  
</code></pre>

<p>Now you have runtime validation and typed output at the same time.  Zod objects also strip unknown properties by default, which makes this useful as a payload whitelist before data ever reaches the database.</p>

<p>If somebody sends:</p>

<pre><code class="language-json">{
  "name": "Taku",
  "email": "test@example.com",
  "admin": true
}
</code></pre>

<p>and <code>admin</code> isn't part of the schema, it doesn't become part of the parsed object.  In Staty I use a similar idea when sanitizing model payloads before they reach the database, and I think this is one of the better places to enforce that kind of behavior.</p>

<h2 id="zodcantdescribeeverything">Zod Can't Describe Everything</h2>

<p>The obvious limitation is that Zod doesn't know everything your database needs to know.  A <code>teamId</code> might reference a Team, an email might need a unique index, a field might need an index or MongoDB may own <code>_id</code>.</p>

<p>Those aren't really validation concerns, so I don't think they need to be forced into the schema itself.  I think of the canonical representation more like:</p>

<pre><code class="language-text">Zod schema  
+
metadata  
</code></pre>

<p>For example:</p>

<pre><code class="language-ts">export const playerMetadata = {  
  email: { unique: true },
  teamId: { ref: 'Team', index: true },
};
</code></pre>

<p>Zod 4 has better support for metadata and registries now, which makes this general approach cleaner, but database-specific concepts still need some conventions of your own.  The important part to me is that I still don't want to manually redefine the entire model in another place just because the database needs a few extra details.</p>

<h2 id="generatingthedatabasemodel">Generating the Database Model</h2>

<p>This is where it starts becoming more interesting.  Instead of maintaining a <code>PlayerSchema</code> in Zod and then separately maintaining a <code>PlayerMongooseSchema</code>, you can derive the Mongoose representation from the canonical schema.</p>

<p>A very simplified converter could look something like this:</p>

<pre><code class="language-ts">function zodToMongoose(field) {  
  if (field instanceof z.ZodString) return { type: String };
  if (field instanceof z.ZodNumber) return { type: Number };
  if (field instanceof z.ZodBoolean) return { type: Boolean };

  return { type: Schema.Types.Mixed };
}
</code></pre>

<p>Then you can walk the Zod object:</p>

<pre><code class="language-ts">function toMongooseSchema(schema) {  
  return Object.fromEntries(
    Object.entries(schema.shape).map(([name, field]) =&gt; [
      name,
      zodToMongoose(field),
    ])
  );
}
</code></pre>

<p>And create the model from the generated result:</p>

<pre><code class="language-ts">const Player = model(  
  'Player',
  new Schema(toMongooseSchema(PlayerSchema))
);
</code></pre>

<p>Obviously the real implementation has to understand optional values, arrays, nested objects, dates, refs, indexes and other things.  But I don't think putting a 100-line converter into a blog post makes the concept any clearer.</p>

<p>The part I care about is the direction.</p>

<pre><code class="language-text">Zod  
 ↓
Mongoose  
</code></pre>

<p>Instead of:</p>

<pre><code class="language-text">Zod ← developer → Mongoose  
</code></pre>

<p>The second version has two independently maintained definitions.  The first one has a canonical definition and a projection.</p>

<h2 id="mongooseprismaanddrizzlearenotequalhere">Mongoose, Prisma and Drizzle Are Not Equal Here</h2>

<p>Mongoose is probably the cleanest fit for this pattern because its schemas are runtime JavaScript objects.  You can inspect the Zod schema and turn it directly into a Mongoose schema without having to generate an intermediate file.</p>

<p>For example:</p>

<pre><code class="language-ts">teamId: z.string()  
</code></pre>

<p>plus:</p>

<pre><code class="language-ts">teamId: { ref: 'Team' }  
</code></pre>

<p>could become:</p>

<pre><code class="language-ts">teamId: {  
  type: Schema.Types.ObjectId,
  ref: 'Team',
}
</code></pre>

<p>Prisma is a little different because Prisma expects its own schema DSL.  So the flow is more like:</p>

<pre><code class="language-text">Zod  
 ↓
generator  
 ↓
schema.prisma  
 ↓
Prisma  
</code></pre>

<p>The generated output might look like:</p>

<pre><code class="language-prisma">model Player {  
  id       String  @id
  name     String
  email    String  @unique
  teamId   String
  active   Boolean?
}
</code></pre>

<p>If I was doing this with Prisma, I would probably commit the generated <code>schema.prisma</code> and have CI make sure it hasn't drifted:</p>

<pre><code class="language-bash">pnpm generate:prisma  
git diff --exit-code  
</code></pre>

<p>If somebody changes the canonical schema but forgets to regenerate Prisma, the build fails.</p>

<p>Drizzle sits somewhere in the middle because its tables are TypeScript runtime builders.  A table might look like this:</p>

<pre><code class="language-ts">const players = pgTable('players', {  
  name: text('name').notNull(),
  email: text('email').notNull().unique(),
  active: boolean('active'),
});
</code></pre>

<p>So you can write a converter that maps Zod fields into the appropriate Drizzle builders without necessarily generating a separate DSL file.</p>

<pre><code class="language-ts">function zodToDrizzle(name, field) {  
  if (field instanceof z.ZodString) return text(name);
  if (field instanceof z.ZodNumber) return integer(name);
  if (field instanceof z.ZodBoolean) return boolean(name);
}
</code></pre>

<p>I think it's important to be honest about the ergonomics here.  Mongoose is probably the easiest fit, Drizzle is a pretty good fit and Prisma works but requires more traditional code generation.</p>

<p>Also, this doesn't magically make your database interchangeable.  Queries, relations, transactions, migrations, indexes and database-specific features are still going to leak into the application.  What it does is remove one pretty large area of duplication, which is the basic definition of what your data looks like.</p>

<h2 id="canonicaldoesntmeaneverylayerusestheexactsameschema">Canonical Doesn't Mean Every Layer Uses the Exact Same Schema</h2>

<p>Another distinction I think is important is that a canonical schema doesn't mean every part of your application uses the entire schema.  A database Player might contain <code>id</code>, <code>created</code>, <code>updated</code> and <code>internalNotes</code>, while a registration form only needs <code>name</code>, <code>email</code> and <code>teamId</code>.</p>

<p>That is where projections are useful.</p>

<pre><code class="language-ts">const CreatePlayerSchema = PlayerSchema.omit({  
  id: true,
});

const EditPlayerSchema = PlayerSchema.pick({  
  name: true,
  email: true,
});

const PublicPlayerSchema = PlayerSchema.omit({  
  internalNotes: true,
});
</code></pre>

<p>These are different schemas, but they are intentionally different and they all have a relationship back to the canonical model.  That's a lot different than three developers independently creating three separate definitions that just happen to look similar.</p>

<h2 id="generatingmorethancode">Generating More Than Code</h2>

<p>Once you have a canonical machine-readable schema, the generation doesn't really need to stop at database models.  The same information can be used for API documentation, OpenAPI, test fixtures, environment variable validation and other generated artifacts.</p>

<p>If the schema says:</p>

<pre><code class="language-ts">email: z.string().email()  
</code></pre>

<p>your documentation generator already knows it's a string and that it must be an email.  You can also generate valid fixtures for testing rather than having every test manually decide what a valid Player looks like.</p>

<pre><code class="language-ts">const player = generateFixture(PlayerSchema);  
</code></pre>

<p>I've also been using this same general idea for documentation in Staty.  Once the schema and application metadata are machine-readable, that same source can generate developer documentation and even content used by an AI help assistant.</p>

<pre><code class="language-text">Canonical Schema  
       │
       ├── API docs
       ├── developer docs
       └── AI retrieval corpus
</code></pre>

<p>I think that gets pretty interesting because when the actual application changes, the documentation used by the AI can change with it.  The AI doesn't have to rely as much on some Markdown document somebody wrote months ago and forgot to update.</p>

<h2 id="aimakesthismoreimportantnotless">AI Makes This More Important, Not Less</h2>

<p>This is probably the main reason I've been thinking about this pattern more lately.  AI can generate a lot of code very quickly, which is obviously useful, but it can also create duplication very quickly.</p>

<p>An AI agent can easily create:</p>

<pre><code class="language-text">Player.ts  
PlayerDTO.ts  
PlayerRequest.ts  
PlayerResponse.ts  
PlayerForm.ts  
PlayerValidator.ts  
PlayerModel.ts  
</code></pre>

<p>Each file can be perfectly reasonable by itself, but now you have seven representations of basically the same thing.  The cost of writing all of these has dropped close to zero, but the cost of keeping them synchronized has not.</p>

<p>It also creates a context problem for AI.  If an agent is trying to change a Player, it now has to figure out which of those seven files is authoritative and which ones are just copies or variations.</p>

<p>I would rather give the agent a much simpler rule:</p>

<blockquote>
  <p>This is the canonical schema.  Do not redefine the model.  Derive from it.</p>
</blockquote>

<p>That's easier for developers to understand and it's also much easier to put into something like <code>AGENTS.md</code> for AI coding agents.</p>

<h2 id="schemasarestartingtobecomeinputsforaitoo">Schemas Are Starting to Become Inputs for AI Too</h2>

<p>There's another side of this that didn't really exist in the same way before.  Schemas aren't only useful for normal application code anymore.</p>

<p>LLMs increasingly use structured output and tool calling, which means you are already describing the shape of data you expect the model to return.  The same schema that describes a Player to your frontend and backend can potentially also describe that Player to an AI model.</p>

<p>So instead of:</p>

<pre><code class="language-text">PlayerSchema  
   │
   ├── TypeScript
   ├── API
   ├── database
   └── frontend
</code></pre>

<p>you increasingly have:</p>

<pre><code class="language-text">PlayerSchema  
   │
   ├── TypeScript
   ├── API
   ├── database
   ├── frontend
   └── AI
</code></pre>

<p>That makes the investment in having a clean canonical schema a lot more valuable.</p>

<h2 id="becarefulwithdefaults">Be Careful With Defaults</h2>

<p>One issue I ran into with this approach was defaults.  Something as simple as this can look harmless:</p>

<pre><code class="language-ts">active: z.boolean().default(false)  
</code></pre>

<p>But if your database generator reads that and produces:</p>

<pre><code class="language-ts">active: {  
  type: Boolean,
  default: false,
}
</code></pre>

<p>you have now turned a validation default into persistence behavior.</p>

<p>We ran into a version of this with configuration inheritance where there were effectively three different states:</p>

<pre><code class="language-text">undefined → inherit from parent  
false     → explicitly disabled  
true      → explicitly enabled  
</code></pre>

<p>Those three values had different meanings.  Once <code>.default(false)</code> caused <code>undefined</code> to become <code>false</code>, the application could no longer tell the difference between something that had never been configured and something somebody explicitly disabled.</p>

<p>That broke inheritance behavior in a way that wasn't very obvious at first.  Since then I've become a lot more conservative about putting defaults into the canonical schema.</p>

<p>My general rule now is that defaults should belong to the consumer unless the default is really universal.</p>

<p>If a form should initially show an unchecked checkbox:</p>

<pre><code class="language-ts">const formDefaults = {  
  active: false,
};
</code></pre>

<p>that's a frontend concern.</p>

<p>If MongoDB should add a value when a document is created:</p>

<pre><code class="language-ts">const databaseDefaults = {  
  active: false,
};
</code></pre>

<p>that's a database concern.</p>

<p>The canonical schema should describe what the data is and what is valid.  It shouldn't accidentally make business decisions for every layer consuming it.</p>

<h2 id="whyithinkthismattersmorenow">Why I Think This Matters More Now</h2>

<p>Before AI, duplication had a pretty obvious cost because somebody had to manually sit there and write all of it.  Now AI can generate an interface, validator, database model, API type, form schema, tests and documentation almost instantly.</p>

<p>I don't think that means architecture like this matters less.  I think it matters more.</p>

<p>The problem is changing from:</p>

<blockquote>
  <p>How do we write all of this code?</p>
</blockquote>

<p>to:</p>

<blockquote>
  <p>How do we make sure all of this code stays consistent?</p>
</blockquote>

<p>You can always ask an AI agent to update five different definitions every time a model changes.  I'd rather not have five independent definitions in the first place.</p>

<p>The pattern I've been settling on is pretty straightforward: define the model once, derive everything you reasonably can from it, validate data at the boundaries, keep consumer-specific behavior outside the canonical schema and use CI to make sure generated artifacts don't drift.</p>

<p>Zod works pretty well for this in TypeScript because it sits in an interesting middle ground.  It's not your database, ORM, form library or API documentation, but it understands what the data looks like, how it should be validated and what its TypeScript type should be.</p>

<p>That makes it a pretty good canonical layer.  Everything else can be a projection of that definition, and as more code gets written and maintained with AI, I think having a clear answer to "where is the real definition of this model?" becomes a lot more important.</p>]]></content:encoded></item><item><title><![CDATA[When SaaS Becomes a Black Box for AI]]></title><description><![CDATA[<p>I've been thinking about another problem with AI coding tools that I don't hear talked about as much.  A lot of modern applications don't really live entirely inside the codebase anymore.</p>

<p>Over the last 10+ years we've moved more and more functionality into managed platforms.  Authentication goes into Clerk or</p>]]></description><link>https://takuu.me/when-saas-becomes-a-black-box-for-ai/</link><guid isPermaLink="false">480c6e98-9944-4db2-a25d-4d0224e9c434</guid><dc:creator><![CDATA[Taku Uechi]]></dc:creator><pubDate>Sun, 21 Jun 2026 03:32:00 GMT</pubDate><content:encoded><![CDATA[<p>I've been thinking about another problem with AI coding tools that I don't hear talked about as much.  A lot of modern applications don't really live entirely inside the codebase anymore.</p>

<p>Over the last 10+ years we've moved more and more functionality into managed platforms.  Authentication goes into Clerk or Auth0.  Payments go into Stripe.  Search goes into Algolia.  Commerce goes into Shopify.  Feature flags go into LaunchDarkly.</p>

<p>From an engineering perspective this usually makes a lot of sense.  I would much rather use Stripe than build a payment platform from scratch, and I definitely don't want to build authentication, password resets, MFA, OAuth and session management unless I absolutely have to.</p>

<p>The problem is that AI coding tools mostly understand what they can see, and a lot of the actual application is no longer in the repo.</p>

<h2 id="managedapplicationplatforms">Managed Application Platforms</h2>

<p>I think <strong>managed application platforms</strong> is probably the best way to describe this category.  They're more than just normal SaaS products because they're often part of the runtime behavior of your application.  They own application state, configuration and sometimes a pretty significant amount of business logic.</p>

<p>Some obvious examples are:</p>

<pre><code class="language-text id=" wvcms1""="">Clerk  
Shopify  
Stripe  
Auth0 / Okta  
LaunchDarkly  
Algolia  
Contentful  
Sanity  
Salesforce  
ServiceNow  
</code></pre>

<p>The application usually interacts with them through an SDK or API, but the SDK only shows part of what's actually happening.</p>

<p>You might have this in your code:</p>

<pre><code class="language-typescript id=" tgwmkh""="">const user = await currentUser();  
</code></pre>

<p>The AI can understand that line pretty easily.  What it can't necessarily see is everything configured behind it:</p>

<pre><code class="language-text id=" agdn2g""="">organization roles  
permissions  
SSO configuration  
session settings  
MFA requirements  
dashboard settings  
</code></pre>

<p>That configuration still affects the application.  It just doesn't live in Git.</p>

<h2 id="clerk">Clerk</h2>

<p>Clerk is probably one of the clearest examples I've run into personally.</p>

<p>Your application might contain something like:</p>

<pre><code class="language-typescript id=" z9d1sn""="">has({ permission: "org:admin" })  
</code></pre>

<p>From the code this looks pretty simple.  If an admin suddenly can't access something, an AI coding tool might search the repository, inspect the authorization check and conclude that the code looks correct.</p>

<p>The real problem could be that the permission was never assigned to the role in Clerk.</p>

<p>There may be absolutely nothing wrong with the application code.  A human engineer who's been working on the system for a while probably knows to check Clerk.  The AI might spend a bunch of time trying to "fix" code that isn't broken because that external configuration isn't part of the context it has.</p>

<h2 id="shopify">Shopify</h2>

<p>Shopify has the same problem but at a much larger scale.  I've worked with Shopify where a lot of the behavior wasn't really owned by the React application at all.</p>

<p>Products, metafields, discounts, checkout behavior, themes, extensions, merchant configuration and installed apps can all change what happens.</p>

<p>The application might simply do:</p>

<pre><code class="language-typescript id=" fnt0x2""="">const product = await shopify.getProduct(id);  
</code></pre>

<p>but the behavior behind that product could depend on configuration that never appears anywhere in the repository.</p>

<p>This gets especially interesting when something breaks in production.  The code didn't change, but Shopify configuration did.</p>

<p>If the AI only has access to Git, its view of the problem is incomplete before it even starts debugging.</p>

<h2 id="stripe">Stripe</h2>

<p>Stripe is another obvious one because a lot of payment logic looks like normal application logic from the outside:</p>

<pre><code class="language-typescript id=" nxnb9j""="">await stripe.paymentIntents.create(...)  
</code></pre>

<p>But Stripe owns a huge amount of state:</p>

<pre><code class="language-text id=" f8cog3""="">customers  
products  
prices  
subscriptions  
connected accounts  
invoices  
tax configuration  
webhook configuration  
payment methods  
</code></pre>

<p>I've worked with Stripe Connect where the state of the connected account mattered just as much as anything happening in our own database.  An AI looking at the code might see a connected account ID and understand that we're sending money somewhere, but it doesn't know who actually owns that account, whether payouts are enabled, what bank account is attached or what configuration was changed in the Stripe Dashboard.</p>

<p>Again, part of the application is outside the application.</p>

<h2 id="auth0andokta">Auth0 and Okta</h2>

<p>Auth0 and Okta have the same issue as Clerk, especially once you get into larger organizations.  You might have application code that validates a token and checks some claims, while the actual behavior depends on:</p>

<pre><code class="language-text id=" dci9j8""="">roles  
groups  
identity providers  
SSO  
MFA rules  
tenant configuration  
custom actions  
claims  
</code></pre>

<p>A lot of this can change without a deployment, which I think is one of the more interesting parts of the problem.</p>

<p>We've always thought of source control as the history of how the application changed.  That's not completely true anymore.  The application can change while Git stays exactly the same.</p>

<h2 id="launchdarkly">LaunchDarkly</h2>

<p>LaunchDarkly might actually be the purest example.</p>

<p>Your code could contain:</p>

<pre><code class="language-typescript id=" 7kl5s1""="">if (flags.newCheckout) {  
  return &lt;NewCheckout /&gt;;
}

return &lt;OldCheckout /&gt;;  
</code></pre>

<p>The AI sees two code paths, but which one is production actually using?</p>

<p>Maybe both.</p>

<p>The answer could depend on:</p>

<pre><code class="language-text id=" f4yzrb""="">environment  
user ID  
organization  
percentage rollout  
segment  
prerequisite flag  
manual override  
</code></pre>

<p>None of that logic necessarily exists in your repository.</p>

<p>You could ask an AI:</p>

<blockquote>
  <p>Why does Customer A see the new checkout but Customer B doesn't?</p>
</blockquote>

<p>and it could spend a lot of time analyzing React when the actual answer is just a LaunchDarkly targeting rule.</p>

<p>That's a pretty large blind spot.</p>

<h2 id="algolia">Algolia</h2>

<p>Search is another place where a surprising amount of behavior can live outside the code.  I've worked with Algolia where the frontend really only knows how to send a query and display the results.</p>

<p>The actual search behavior can depend on:</p>

<pre><code class="language-text id=" b8ahot""="">ranking  
searchable attributes  
facets  
synonyms  
replicas  
merchandising  
index configuration  
</code></pre>

<p>Suppose somebody says:</p>

<blockquote>
  <p>Search results are bad for "black dress."</p>
</blockquote>

<p>The AI opens the frontend and finds:</p>

<pre><code class="language-typescript id=" k8up0m""="">index.search("black dress");  
</code></pre>

<p>There's not much to fix there.</p>

<p>The problem could be that somebody changed ranking configuration or synonyms inside Algolia.  A human who knows the application understands that search isn't just code.  The AI has to somehow be given that context.</p>

<h2 id="contentfulandsanity">Contentful and Sanity</h2>

<p>CMS platforms create a similar problem, although in a slightly different way.</p>

<p>Your React application might know about:</p>

<pre><code class="language-typescript id=" q7otpw""="">article.title  
article.heroImage  
article.body  
</code></pre>

<p>but the actual content model, published entries, references, localization and editorial state live somewhere else.</p>

<p>This isn't necessarily traditional business logic, but it still affects application behavior.  An AI can look at the component and decide that <code>heroImage</code> should always exist because the TypeScript interface says it's required, while an editor may have created 300 older articles before that field existed.</p>

<p>The production data is telling a different story than the code.</p>

<p>Sanity is a little better here because more of its schema can be represented as code, but the actual content and relationships still exist outside the application repository.</p>

<h2 id="salesforceandservicenow">Salesforce and ServiceNow</h2>

<p>Salesforce is where this problem can get pretty extreme.  I've seen enterprise applications where Salesforce isn't just a database.  It contains a huge amount of business behavior.</p>

<p>Things like:</p>

<pre><code class="language-text id=" b2w3iy""="">validation rules  
flows  
approval processes  
permissions  
custom objects  
automation  
workflow rules  
</code></pre>

<p>Imagine your application does this:</p>

<pre><code class="language-typescript id=" vz37cz""="">await salesforce.updateCustomer(customer);  
</code></pre>

<p>Then something unexpected happens.</p>

<p>Maybe an approval process starts.  Maybe another record gets updated.  Maybe an email gets sent.  Maybe the update is rejected because of a validation rule.</p>

<p>None of that behavior has to exist in your application's repository.  You could give the AI every line of your code and it still wouldn't understand the complete workflow.</p>

<p>ServiceNow is very similar.  A lot of enterprise workflows can live almost completely inside the platform through forms, business rules, approvals, permissions, integrations and automation.  From the application side you might just see an API call, while behind that call there could be years of business logic.</p>

<p>This is probably where the term "black box" starts feeling pretty accurate.</p>

<h2 id="therepositoryisnttheapplicationanymore">The Repository Isn't the Application Anymore</h2>

<p>This is the part I find most interesting.</p>

<p>For a lot of modern applications, the real system looks closer to:</p>

<pre><code class="language-text id=" 1ak6wr""="">Application Repository  
        +
MongoDB  
        +
Clerk  
        +
Stripe  
        +
Shopify  
        +
Algolia  
        +
Feature Flags  
        +
CMS  
        +
Production Configuration  
        =
The Real Application  
</code></pre>

<p>But an AI coding agent might only see:</p>

<pre><code class="language-text id=" 7l5wvo""="">Application Repository  
</code></pre>

<p>Maybe the database schema too, if you're lucky.</p>

<p>That's a huge difference in context, and AI is extremely dependent on context.</p>

<p>I think this also changes the idea of "give the AI the whole repo."  Even if you give it every file in Git, you still may not be giving it the whole application.</p>

<h2 id="humanshaveinstitutionalcontext">Humans Have Institutional Context</h2>

<p>A senior engineer working on an application for a few years picks up a lot of information that never gets written down.</p>

<p>You start knowing things like:</p>

<pre><code class="language-text id=" 64e5nf""="">That permission is configured in Clerk.

That product price comes from Stripe.

Don't change that field, Shopify owns it.

That search issue is probably Algolia.

That customer is on a feature flag override.  
</code></pre>

<p>None of those things are necessarily obvious from reading the code.</p>

<p>When another human joins the team, that knowledge gets transferred slowly through pull requests, Slack messages, documentation and somebody eventually saying, "oh yeah, that's weird because..."</p>

<p>AI doesn't really get that same onboarding.  Every new coding session can effectively start with:</p>

<blockquote>
  <p>Here's the repository.  Figure it out.</p>
</blockquote>

<p>That's probably fine when most of the application lives in the repository.  It's much harder when half the application lives in dashboards.</p>

<h2 id="vendorlockinvscontextlockout">Vendor Lock-In vs Context Lock-Out</h2>

<p>The traditional criticism of these platforms has always been vendor lock-in.  You build heavily around Shopify and now moving away from Shopify is difficult.  You build around Stripe and now Stripe is deeply embedded in your payment infrastructure.</p>

<p>That's still true.</p>

<p>But I think AI introduces another problem that I would call <strong>context lock-out</strong>.</p>

<p>Vendor lock-in is basically:</p>

<blockquote>
  <p>It's difficult to move away from this platform.</p>
</blockquote>

<p>Context lock-out is:</p>

<blockquote>
  <p>It's difficult for an AI agent to understand the application because important parts of the application live inside this platform.</p>
</blockquote>

<p>The application can still work perfectly fine and the developer can still understand it.  The problem is that the AI has an incomplete model of the system.</p>

<p>I think that's becoming a real architectural cost.</p>

<h2 id="thisdoesntmeanweshouldstopusingsaas">This Doesn't Mean We Should Stop Using SaaS</h2>

<p>I'm definitely not suggesting we start rebuilding all of this ourselves.  That would probably be much worse.</p>

<p>I don't want our authentication implementation sitting in 30,000 lines of custom code just so an AI can read it.  The benefits of these platforms are still huge:</p>

<pre><code class="language-text id=" sqdzos""="">less code  
faster development  
better security  
specialized infrastructure  
compliance  
scalability  
reliability  
</code></pre>

<p>And generally fewer things we have to maintain.</p>

<p>The tradeoff is that we're moving application knowledge somewhere else.  That was already a problem for developers, but AI makes the cost much more obvious because the quality of the output depends so much on the context the model actually has access to.</p>

<h2 id="maybetheseplatformsneedtobecomeainativetoo">Maybe These Platforms Need to Become AI-Native Too</h2>

<p>I don't think the obvious solution is putting everything back into the repository.  It's probably giving AI access to more of the external context.</p>

<p>Imagine an AI coding agent being able to inspect:</p>

<pre><code class="language-text id=" qtr3rx""="">Clerk roles and permissions  
Stripe products and subscriptions  
Shopify metafields and configuration  
LaunchDarkly targeting rules  
Algolia index configuration  
Contentful schemas  
Salesforce flows  
</code></pre>

<p>Now when you ask:</p>

<blockquote>
  <p>Why doesn't this user have access?</p>
</blockquote>

<p>the AI could inspect both:</p>

<pre><code class="language-text id=" 91hcfk""="">application code  
+
Clerk configuration  
</code></pre>

<p>That's a much more useful debugging environment.</p>

<p>Some of this is already possible through APIs, MCP servers, CLIs and other integrations, and I think that's going to become increasingly important.</p>

<p>It's probably not enough for AI coding tools to understand the repo.</p>

<p>Eventually they need to understand the <strong>application environment</strong>.</p>

<h2 id="thehiddencomplexityneverreallywentaway">The Hidden Complexity Never Really Went Away</h2>

<p>For years we've been moving functionality out of our applications and into managed platforms.  For the most part, I still think that was the right decision.</p>

<p>We write less code, ship faster and let companies that specialize in authentication, payments, commerce or search handle the difficult parts.</p>

<p>AI changes the tradeoff a little.</p>

<p>The better these coding tools get, the more valuable complete context becomes.  A modern application's context isn't necessarily in Git anymore.  It's spread across the repository, database and probably five or ten different SaaS dashboards.</p>

<p>We've spent years making applications easier to build by hiding complexity behind APIs.  AI is starting to make something else obvious: the complexity may be hidden, but it was still part of the application the whole time.</p>]]></content:encoded></item><item><title><![CDATA[Why AI Makes TypeScript More Useful]]></title><description><![CDATA[<p>I've used TypeScript for years mainly because it makes larger Javascript applications easier to maintain.  That hasn't really changed, but what has changed is that AI is now writing a much larger percentage of the code.</p>

<p>The more I use AI coding tools, the more I think TypeScript becomes even</p>]]></description><link>https://takuu.me/why-typescript-matters-more-in-the-age-of-ai/</link><guid isPermaLink="false">4bac842a-4c7a-4c74-8ab1-c23f37013812</guid><dc:creator><![CDATA[Taku Uechi]]></dc:creator><pubDate>Fri, 10 Apr 2026 23:46:00 GMT</pubDate><content:encoded><![CDATA[<p>I've used TypeScript for years mainly because it makes larger Javascript applications easier to maintain.  That hasn't really changed, but what has changed is that AI is now writing a much larger percentage of the code.</p>

<p>The more I use AI coding tools, the more I think TypeScript becomes even more valuable because it gives AI more context about what the application is actually supposed to do.  Javascript is flexible, which is obviously one of the reasons people like it, but flexibility also means ambiguity.  A developer who has worked on an application for three years can usually fill in a lot of those blanks mentally.  An AI agent doesn't necessarily have that institutional knowledge unless it can find it somewhere in the codebase.</p>

<h2 id="typesgiveaimorecontext">Types Give AI More Context</h2>

<p>Take something simple like this:</p>

<pre><code class="language-typescript">function updateRegistration(data: any) {  
  // ...
}
</code></pre>

<p>A developer familiar with the application might already know what <code>data</code> is supposed to contain.  Maybe it looks something like this:</p>

<pre><code class="language-typescript">{
  teamId: string;
  divisionId: string;
  status: string;
  players: Player[];
}
</code></pre>

<p>AI doesn't automatically know that.  It has to inspect the function, search where it's being called, look at other objects that seem related and then infer what the shape probably is.</p>

<p>Now compare that with:</p>

<pre><code class="language-typescript">interface RegistrationUpdate {  
  teamId: string;
  divisionId: string;
  status: RegistrationStatus;
  players: Player[];
}

function updateRegistration(data: RegistrationUpdate) {  
  // ...
}
</code></pre>

<p>There is a lot less to guess.  It gets even better with unions:</p>

<pre><code class="language-typescript">type RegistrationStatus =  
  | "pending"
  | "accepted"
  | "waitlisted"
  | "cancelled";
</code></pre>

<p>If an AI agent is adding a registration workflow, it now has a very obvious list of valid states.  Without that type it might search through the repository, find <code>"inactive"</code>, <code>"removed"</code>, <code>"cancelled"</code> and <code>"dropped"</code> in various pieces of old code and decide that one of those is probably the right value.</p>

<p>That is exactly the kind of mistake AI can make pretty easily.  The code might look completely reasonable, the naming might fit the application, but the assumption itself is wrong.</p>

<p><code>any</code> was always dangerous, but I think it's a little more expensive now because AI doesn't have all the knowledge that developers slowly accumulate while working on a system.  Types move some of that knowledge out of people's heads and put it directly into the code.</p>

<h2 id="aialsomakesstrongtypingcheaper">AI Also Makes Strong Typing Cheaper</h2>

<p>One of the complaints about TypeScript over the years has always been that it creates extra work.  You have to create interfaces, DTOs, enums, generics and sometimes spend way too much time convincing TypeScript that something you already know is valid is actually valid.</p>

<p>That still happens.  The difference is that AI is pretty good at doing a lot of the boring part now.</p>

<p>If I have an API response like this:</p>

<pre><code class="language-json">{
  "id": "123",
  "name": "Tigers",
  "division": {
    "id": "456",
    "name": "Mens Open"
  }
}
</code></pre>

<p>I can have an AI coding tool generate the TypeScript type or Zod schema basically immediately.  The same thing applies to a lot of mechanical transformations:</p>

<pre><code class="language-text">API response  
→ TypeScript type
→ Zod schema
→ test fixture
</code></pre>

<p>The cost of creating decent type coverage has gone down quite a bit.</p>

<p>At the same time, AI is also increasing the amount of code we can produce.  If one engineer can now create significantly more code in the same amount of time, I think guardrails become more important, not less.</p>

<p>An AI can write a lot of bad Javascript very quickly.  At least with TypeScript, the compiler gets a vote.</p>

<p>That's one of the reasons I think the tradeoff has shifted.  We have less excuse for leaving something vaguely typed because a lot of the repetitive work can now be generated, while the downside of incorrect generated code is actually becoming larger because we're producing more of it.</p>

<h2 id="sharingmodelsandbusinesslogicacrossthestack">Sharing Models and Business Logic Across the Stack</h2>

<p>One thing I've always liked about using TypeScript on both the frontend and backend is being able to share models.  This becomes even more useful with AI because it gives the agent fewer representations of the same thing to reconcile.</p>

<p>For example:</p>

<pre><code class="language-typescript">export interface RegistrationTeam {  
  id: string;
  name: string;
  divisionId: string;
  status: RegistrationStatus;
  players: Player[];
}
</code></pre>

<p>That type can potentially be shared by:</p>

<pre><code class="language-text">React application  
admin application  
Node API  
background workers  
tests  
</code></pre>

<p>Instead of having one object shape on the frontend, another on the backend and maybe a slightly different version in some worker or admin application, there is one shared definition.</p>

<p>The same thing applies to business logic.  For example:</p>

<pre><code class="language-typescript">export function canRegister(  
  division: Division,
  team: RegistrationTeam
) {
  return (
    team.players.length &gt;= division.minPlayers &amp;&amp;
    team.players.length &lt;= division.maxPlayers
  );
}
</code></pre>

<p>The frontend can use that function to determine whether a registration is valid before submission, and the backend can use the same function before actually saving anything.  The backend should still be the source of truth, but there isn't much reason to independently implement the same rule twice.</p>

<p>In the AI era I think this is even more valuable because there is one obvious place for the agent to find the rule.</p>

<p>Instead of:</p>

<pre><code class="language-text">frontend implementation  
backend implementation  
admin implementation  
</code></pre>

<p>you have:</p>

<pre><code class="language-text">shared registration logic  
</code></pre>

<p>The less duplicated business logic there is, the less chance the AI has to update one copy while forgetting another.</p>

<p>This lines up really well with monorepos too.  If the frontend, API, workers and shared libraries all live in the same repository and share TypeScript packages, an AI agent has a much better chance of understanding how a change actually moves through the system.</p>

<h2 id="onelanguagecancoveralotmoreoftheapplication">One Language Can Cover a Lot More of the Application</h2>

<p>Javascript started in the browser, but TypeScript can cover a pretty large percentage of a modern application now.</p>

<p>You can use it for:</p>

<pre><code class="language-text">React  
Next.js  
Node.js  
React Native  
Electron  
Cloudflare Workers  
serverless functions  
background jobs  
build scripts  
tests  
</code></pre>

<p>Obviously that doesn't mean everything should be written in TypeScript.  There are plenty of good reasons to use Python, Go, Rust, Java or whatever else makes sense for a particular problem.</p>

<p>But for a normal SaaS application, using one language across a large percentage of the stack has some pretty obvious advantages.  A developer can move from a React component to an API endpoint to a background worker to a shared library without constantly switching languages and ecosystems.</p>

<pre><code class="language-text">React component  
→ API endpoint
→ job worker
→ shared library
</code></pre>

<p>AI gets a similar benefit.  If the agent already understands the TypeScript types, conventions and patterns being used in one part of the application, a lot of that context transfers naturally into another part.</p>

<p>It isn't jumping from TypeScript on the frontend to Java on the backend and then Python for a worker while also trying to figure out how three different implementations map back to the same business domain.</p>

<p>That alone isn't a reason to rewrite an existing system, but if I'm starting a new application today and TypeScript is already a good fit for the workload, AI being able to operate across more of the stack with the same language is another advantage.</p>

<h2 id="thecompilerbecomespartoftheaifeedbackloop">The Compiler Becomes Part of the AI Feedback Loop</h2>

<p>I think this might be the biggest advantage.</p>

<p>AI can write some code and immediately find out whether its assumptions were structurally wrong.</p>

<p>The loop looks something like:</p>

<pre><code class="language-text">AI writes code  
    ↓
tsc  
    ↓
compiler errors  
    ↓
AI fixes code  
    ↓
tsc again  
</code></pre>

<p>That feedback loop is really useful.</p>

<p>For example, AI might generate:</p>

<pre><code class="language-typescript">registration.playerCount  
</code></pre>

<p>when the actual model is:</p>

<pre><code class="language-typescript">registration.players.length  
</code></pre>

<p>In Javascript, you might not notice the mistake until that particular code path runs.  TypeScript can immediately return something like:</p>

<pre><code class="language-text">Property 'playerCount' does not exist on type 'RegistrationTeam'  
</code></pre>

<p>Now the AI has deterministic feedback instead of having to guess whether its implementation was correct.</p>

<p>I think this is important because LLMs are probabilistic.  They can generate something that looks correct, follows the naming conventions of the application and is still completely wrong.</p>

<p>The compiler doesn't really care how convincing the code looks.  Either the property exists or it doesn't.</p>

<p>Obviously this doesn't mean TypeScript proves your application is correct.  You can write completely wrong business logic that compiles perfectly:</p>

<pre><code class="language-typescript">function calculateRefund(payment: number) {  
  return payment * 2;
}
</code></pre>

<p>TypeScript has no problem with that.  Tests still matter, runtime validation still matters and code review still matters.</p>

<p>But TypeScript eliminates a pretty large category of structural mistakes before the tests even run, and I think that becomes especially valuable when the code is being generated by AI.</p>

<h2 id="typescriptalsohelpscentralizecontext">TypeScript Also Helps Centralize Context</h2>

<p>I've been thinking a lot lately about how important context is for AI coding tools, and this is part of why I've become more interested in monorepos.</p>

<p>If your frontend, API, workers and shared libraries all live together, the AI has a better chance of understanding the application as one system instead of a bunch of isolated repositories.</p>

<p>TypeScript adds another layer to that.</p>

<p>The monorepo gives the AI more code.</p>

<p>TypeScript gives the AI more information about that code.</p>

<p>A repository might contain thousands of functions and objects, but types start describing how those pieces are related.</p>

<p>Something like:</p>

<pre><code class="language-typescript">interface Payment {  
  registrationId: string;
  userId: string;
  amount: number;
  status: PaymentStatus;
}
</code></pre>

<p>already tells the AI that payments are related to registrations and users.</p>

<p>Then a function signature like:</p>

<pre><code class="language-typescript">function refundPayment(  
  payment: Payment,
  registration: Registration
): RefundResult
</code></pre>

<p>describes another relationship.</p>

<p>You start building a kind of graph of the application just through the type system.  Humans get value out of this too, but I think it's especially useful for AI because the agent doesn't have years of experience with the application and doesn't know all of the relationships by memory.</p>

<p>The more of the architecture and business domain we can make explicit, the less the AI has to infer.</p>

<h2 id="whyithinktypescriptismorevaluablenow">Why I Think TypeScript Is More Valuable Now</h2>

<p>TypeScript was already useful before AI.  It made Javascript safer, made refactoring easier and helped larger teams understand how data moved through an application.</p>

<p>I think AI increases the value of those same features.</p>

<p>AI makes code significantly cheaper to generate, but that doesn't necessarily make correctness cheaper.  If anything, I think it makes correctness and context more valuable because there is simply more code being produced.</p>

<p>Types give AI more information about what the application expects, the compiler gives it an immediate feedback loop, and using TypeScript across more of the stack makes it easier to share models and business logic instead of duplicating them.</p>

<p>The interesting part to me is that TypeScript may be becoming more important for a reason that wasn't really part of the original pitch.</p>

<p>It isn't just making Javascript easier for developers to understand.  It's also making the application easier for AI to understand.</p>]]></content:encoded></item><item><title><![CDATA[The Case for Monorepos in the Age of AI]]></title><description><![CDATA[<p>I've gone back and forth on monorepos over the years.  There are obvious benefits: shared packages are easier, types can be reused, frontend and backend code can live closer together and you don't have to publish an internal package every time you change one interface.</p>

<p>There are also obvious downsides.</p>]]></description><link>https://takuu.me/the-case-for-monorepos-in-the-age-of-ai/</link><guid isPermaLink="false">199e1362-989a-4ba5-aa0c-df2de7cc0fe1</guid><dc:creator><![CDATA[Taku Uechi]]></dc:creator><pubDate>Sat, 22 Nov 2025 21:21:00 GMT</pubDate><content:encoded><![CDATA[<p>I've gone back and forth on monorepos over the years.  There are obvious benefits: shared packages are easier, types can be reused, frontend and backend code can live closer together and you don't have to publish an internal package every time you change one interface.</p>

<p>There are also obvious downsides.  The repo gets huge, build systems get more complicated, CI can get expensive and if boundaries aren't enforced properly everything eventually starts importing everything else.</p>

<p>AI changes the tradeoff a little bit though.</p>

<p>The more I've been using AI for development, the more I think having related applications in the same repository is becoming an advantage.  Not because monorepos suddenly got simpler, but because context is becoming a much bigger part of the development environment.</p>

<h2 id="themorecontextthebetter">The More Context the Better</h2>

<p>One of the biggest limitations with AI right now is context.  If I'm asking an engineer to change a feature, they usually already know some things about the application.  They know where the API is, how authentication works, which database models are involved and probably which other application consumes the same API.</p>

<p>AI doesn't necessarily know any of that unless you give it the context.</p>

<p>If everything is in one repository, it can potentially see something like:</p>

<pre><code class="language-text">/apps/web
/apps/admin
/apps/api
/packages/types
/packages/ui
/packages/utils
/packages/config
</code></pre>

<p>Now if I ask:</p>

<pre><code class="language-text">Add a new registration status and update the admin UI  
</code></pre>

<p>the AI can potentially find the backend enum, database schema, API response, shared TypeScript type and the frontend component using it.</p>

<p>That's a lot better than giving it access to only the admin repository and having it guess what the backend looks like.</p>

<p>For AI, context is basically part of the development environment now.</p>

<h2 id="repositoryboundariesarealsocontextboundaries">Repository Boundaries Are Also Context Boundaries</h2>

<p>I've worked on systems where the frontend, API and other services were all in separate repositories.  There are plenty of good reasons for doing that, especially once teams get larger.</p>

<p>The problem with AI is that the repository boundary also becomes a context boundary.</p>

<p>Imagine:</p>

<pre><code class="language-text">frontend-repo  
api-repo  
jobs-repo  
shared-library-repo  
</code></pre>

<p>You ask an AI agent to change something in <code>frontend-repo</code>, and it finds:</p>

<pre><code class="language-typescript">await api.updateRegistration(data);  
</code></pre>

<p>It can see that the frontend calls an API, but it doesn't necessarily know what <code>updateRegistration</code> actually does, what validation happens on the backend or whether some background job gets triggered afterward.</p>

<p>A human engineer who's worked on the system for two years might already know all of that.  The AI doesn't.</p>

<p>You can obviously give AI access to multiple repositories, and I'm sure tooling around that will continue to improve, but at some point you're basically rebuilding a shared view of the system anyway.</p>

<p>That's one reason monorepos are starting to look more interesting to me again.</p>

<h2 id="sharedbusinesslogicwasalreadyuseful">Shared Business Logic Was Already Useful</h2>

<p>Shared business logic was probably one of the strongest reasons I liked monorepos even before AI.  There are always rules that multiple parts of an application need to understand:</p>

<pre><code class="language-text">registration status  
permissions  
pricing rules  
validation  
date formatting  
API contracts  
sports-specific rules  
</code></pre>

<p>Without a monorepo, you have a few choices.  You can duplicate the logic, publish a shared npm package, create another internal service or just accept that slightly different versions of the same rule are going to exist in different applications.</p>

<p>None of those are necessarily terrible, but they all add some overhead.</p>

<p>In a monorepo you can do something like:</p>

<pre><code class="language-text">/packages/registration
/packages/permissions
/packages/types
</code></pre>

<p>and have multiple applications depend on the same implementation.</p>

<p>This also gives AI something pretty useful: one obvious place to look.</p>

<p>Instead of trying to figure out which of three different implementations is correct, there's hopefully one package where that business rule lives.</p>

<p>Of course, "hopefully" is doing a lot of work there.  A badly organized monorepo can still have five implementations of the same thing, which is really just the worst of both worlds.</p>

<h2 id="crossapplicationchangesarewherethisgetsinteresting">Cross-Application Changes Are Where This Gets Interesting</h2>

<p>This is probably where I see the biggest advantage with AI.</p>

<p>A feature that sounds simple can touch a surprising amount of the application.</p>

<p>For example:</p>

<pre><code class="language-text">Add waitlist support.  
</code></pre>

<p>That might actually mean:</p>

<pre><code class="language-text">Mongo schema  
→ API
→ business logic
→ admin application
→ registration application
→ email notification
→ background job
→ tests
</code></pre>

<p>Historically that could mean several pull requests across several repositories.  With a monorepo, an AI agent can at least see the entire change.</p>

<p>That doesn't mean I would blindly let it modify everything.  But it can understand the dependency chain much better.</p>

<p>It can find where <code>RegistrationTeam</code> is created, where the API serializes it, which React components consume it and which tests are likely to break after the schema changes.</p>

<p>That's a lot more useful than asking an AI tool to modify one isolated piece and then discovering three repositories later that the change broke something else.</p>

<h2 id="typesbecomepartofthecontext">Types Become Part of the Context</h2>

<p>I've always liked TypeScript mainly because it makes larger Javascript applications easier to maintain.  With AI, I've started appreciating another benefit: types give the model clues about how the application is supposed to work.</p>

<p>For example:</p>

<pre><code class="language-typescript">type RegistrationStatus =  
  | "pending"
  | "accepted"
  | "waitlisted"
  | "cancelled";
</code></pre>

<p>is a lot more useful than having the model search through random strings in the codebase and try to figure out which values are valid.</p>

<p>If the frontend and backend share that type in a monorepo, even better.</p>

<p>The type starts acting like documentation that is harder to let drift because the compiler complains when something no longer lines up.</p>

<p>This is one of the reasons I think good typing, schemas and shared contracts matter even more with AI.  The AI doesn't have years of context in its head, so anything you can make explicit in the repository helps.</p>

<h2 id="morecontextisntalwaysbetter">More Context Isn't Always Better</h2>

<p>There is an obvious downside to giving AI more context.</p>

<p>More context isn't necessarily better if the context is garbage.</p>

<p>If your monorepo looks like:</p>

<pre><code class="language-text">/helpers
/helpers2
/common
/shared
/shared-new
/old-api
/api-new
/utils
/utils-final
</code></pre>

<p>the AI is probably going to have the exact same reaction a new engineer would have:</p>

<blockquote>
  <p>Which one am I supposed to use?</p>
</blockquote>

<p>This is one area where I think AI actually increases the importance of good architecture.</p>

<p>Packages need clear responsibilities.  Dependencies should go in one direction.  Shared code should actually be shared, and old code should eventually be removed instead of sitting around forever waiting for someone or some AI agent to accidentally use it.</p>

<p>We used to organize code mainly so another engineer could understand it.</p>

<p>Now we're organizing it so another engineer and an AI agent can understand it.</p>

<h2 id="testsmattermorewhenchangesgetbigger">Tests Matter More When Changes Get Bigger</h2>

<p>AI makes it very easy to change a lot of code quickly.  That's both the good part and the scary part.</p>

<p>An AI agent might modify six packages in a few minutes.  If the repository has good tests, that can be great because it can immediately run them and see what it broke.</p>

<p>If the repository doesn't have tests, then you basically have a very fast junior engineer making changes across the entire application.</p>

<p>Probably not ideal.</p>

<p>A monorepo can make testing cross-application changes easier because everything is available to the same CI system:</p>

<pre><code class="language-text">change package  
→ identify affected apps
→ build
→ unit tests
→ integration tests
→ E2E tests
</code></pre>

<p>Tools like Nx and Turborepo already do a lot of the dependency graph work needed to figure out what actually needs to run.</p>

<p>That becomes more useful when AI is generating more changes than engineers traditionally would.  If the agent changes one shared package, the build system should be able to tell it exactly which applications and tests are affected.</p>

<h2 id="thebuildsystemstillmatters">The Build System Still Matters</h2>

<p>The obvious downside of a monorepo is that eventually somebody is going to run:</p>

<pre><code class="language-bash">npm test  
</code></pre>

<p>and accidentally test the entire company.</p>

<p>That doesn't scale.</p>

<p>If AI agents are going to work inside large repositories, the build tooling needs to understand what actually changed.  If a shared UI component changes, maybe three applications need to rebuild.  If an API-only package changes, the marketing website probably doesn't care.</p>

<p>This is where Nx, Turborepo, pnpm workspaces, Bazel and similar tooling become pretty important.</p>

<p>The AI should be able to make a change and run only the relevant builds and tests instead of treating the monorepo like one enormous application.</p>

<p>Otherwise the extra context comes with a huge performance penalty.</p>

<h2 id="boundariesstillmatter">Boundaries Still Matter</h2>

<p>One of the common arguments against monorepos is that developers can access too much.</p>

<p>I think that's actually an even bigger concern with AI.</p>

<p>If everything is sitting next to everything else, it's very easy for an agent to take a shortcut.  Instead of calling the proper API, it might import something directly from another package.  Instead of respecting a service boundary, it might reuse an internal database model because it happens to be available.</p>

<p>Technically the code might work.</p>

<p>Architecturally you just created something terrible.</p>

<p>So I don't think the lesson is:</p>

<pre><code class="language-text">Put everything in one repo  
and let AI figure it out.  
</code></pre>

<p>It's more like:</p>

<pre><code class="language-text">Put related things in one repo,  
but make the boundaries extremely obvious.  
</code></pre>

<p>AI needs guardrails just like developers do.</p>

<p>Probably more.</p>

<h2 id="andthentherearelayoffs">And Then There Are Layoffs...</h2>

<p>There is also another slightly depressing argument for monorepos in the age of AI.</p>

<p>Companies have fewer engineers.</p>

<p>So... monorepos are better now?</p>

<p>I'm joking.</p>

<p>Mostly.</p>

<p>One traditional argument against monorepos was that with hundreds or thousands of engineers working in the same repository you need really good tooling, ownership rules and coordination.  If you have fewer engineers touching the codebase, some of those problems naturally become smaller.</p>

<p>Meanwhile those same engineers are now using AI and potentially making changes across a much larger portion of the stack.</p>

<p>So we might end up with fewer humans touching more code.</p>

<p>Which weirdly makes the monorepo model make even more sense.</p>

<p>I don't know if that's progress or just the industry finding a creative way to make everyone responsible for more stuff.</p>

<h2 id="monoreposstillarentalwaystherightanswer">Monorepos Still Aren't Always the Right Answer</h2>

<p>I don't think AI suddenly means every company should move everything into one monorepo.  There are still good reasons to keep repositories separate.</p>

<p>Completely independent services, different security requirements, different teams, different deployment models and different technology stacks can all justify separate repositories.</p>

<p>But I do think AI changes one part of the equation.</p>

<p>Repository boundaries aren't only organizational boundaries anymore.</p>

<p>They're also context boundaries.</p>

<p>And when you're working with AI, context is extremely valuable.</p>

<p>The more interesting question might not be whether monorepos are better than multiple repositories.  It might be:</p>

<pre><code class="language-text">How much of the system does the developer  
and the AI working with them  
need to understand to make a correct change?  
</code></pre>

<p>If the answer is "most of it," then having most of it in one place starts looking pretty attractive.</p>]]></content:encoded></item><item><title><![CDATA[What Changes When Your Application Depends on AI]]></title><description><![CDATA[<p>I've been thinking about some of the application dependencies that become more important once AI is introduced into an application.  A lot of the infrastructure isn't actually new.  We already use Redis, queues, workers, Kafka, databases, third party APIs, caching and monitoring in normal applications.  AI just creates some interesting</p>]]></description><link>https://takuu.me/what-changes-when-your-application-depends-on-ai/</link><guid isPermaLink="false">928097e2-445a-4a0e-b22f-70deca614695</guid><dc:creator><![CDATA[Taku Uechi]]></dc:creator><pubDate>Tue, 15 Oct 2024 18:28:00 GMT</pubDate><content:encoded><![CDATA[<p>I've been thinking about some of the application dependencies that become more important once AI is introduced into an application.  A lot of the infrastructure isn't actually new.  We already use Redis, queues, workers, Kafka, databases, third party APIs, caching and monitoring in normal applications.  AI just creates some interesting cases where you start depending on these much more heavily.</p>

<p>One major difference is that we're used to application code being mostly deterministic.  Given the same inputs we generally expect our code to do the same thing.  AI isn't really like that.  It can be slow, responses can be different for the same input and sometimes it can give you something completely unintended.</p>

<p>And of course human input can be... creative.  If you give people a textbox they'll eventually paste things into it you never expected.</p>

<p>Here are some of the dependencies I've been running into or thinking about while building AI functionality.</p>

<h2 id="aiprovideroutagesandavailability">AI Provider Outages and Availability</h2>

<p>Once you integrate OpenAI, Anthropic or another provider into a workflow, it's basically another external service that can go down.  We've dealt with this forever with Stripe, Cloudflare, Elasticsearch and pretty much any service we don't completely control, but with AI there's a tendency to make the model part of the main application flow.</p>

<p>For example:</p>

<pre><code class="language-text">User Request  
    ↓
Application API  
    ↓
OpenAI  
    ↓
Parse Response  
    ↓
Continue Workflow  
</code></pre>

<p>This works fine until OpenAI takes 45 seconds to return or returns a 500.  If the application has a 30 second HTTP timeout then we now have a failed request even though technically the AI provider may eventually complete the work.</p>

<p>For anything that can take awhile, I've been leaning toward treating AI work more like a job than a normal request.  I've built systems using Redis backed queues and workers for long running or scheduled work and the exact same pattern applies pretty naturally here.  Put the work into a queue, let a worker process it and either poll for the result or push it back through a WebSocket when completed.</p>

<p>Retries also have to be handled carefully.  Retrying a normal GET request is pretty harmless, but if the AI is calling another service that creates a payment, sends an email or modifies data then retrying the entire workflow can potentially execute the action twice.  At that point things like idempotency become just as important as the AI call itself.</p>

<h2 id="promptsandmodelversions">Prompts and Model Versions</h2>

<p>Prompts are starting to feel like another form of application code.  A pretty small change to a system prompt can completely change what comes back from the model.</p>

<p>For example:</p>

<pre><code class="language-text">Extract the information from this document.  
</code></pre>

<p>and:</p>

<pre><code class="language-text">Extract the information from this document.  
Only return information explicitly found in the document.  
Do not guess missing values.  
Return the result using this JSON schema...  
</code></pre>

<p>are technically asking for the same thing but can have very different results.</p>

<p>Because of this I think prompts should be kept in source control and changes should be tested similar to other application changes.  I probably wouldn't bury an important production prompt as a random string inside a React component anymore.</p>

<p>The model version becomes part of this dependency too.  You can have the same application code and the same prompt but get different behavior after changing models.  This makes upgrading the model a little different from upgrading most libraries.</p>

<p>Traditionally we expect something close to:</p>

<pre><code class="language-text">input + code = output  
</code></pre>

<p>With an AI feature it's more like:</p>

<pre><code class="language-text">input + prompt + model + context = probably the output we want  
</code></pre>

<p>AI models are non-deterministic, although there are settings that can make the output more consistent.  The important thing from an application perspective is that I wouldn't assume the same prompt and input will always produce exactly the same response.  If I'm changing a model in production I want to run our real use cases against it first.</p>

<h2 id="datacontextandotherapis">Data, Context and Other APIs</h2>

<p>The model is only one part of most useful AI applications.  Unless you're asking general questions, it needs some way to know about your application's data.</p>

<p>I've worked on a RAG platform where documents went through ingestion, ETL, normalization, metadata enrichment and source prioritization before the information ever got to the model.</p>

<p>Something roughly like:</p>

<pre><code class="language-text">Documents  
    ↓
Ingestion / ETL  
    ↓
Normalize + Metadata  
    ↓
Search / Retrieval  
    ↓
Context  
    ↓
AI  
</code></pre>

<p>Once you build something like this it becomes pretty obvious that improving the model doesn't automatically improve the application.  If search pulls the wrong document or your ingestion process has bad metadata, the AI is working with bad information.</p>

<p>Garbage in, garbage out still applies.  AI just makes the garbage sound more convincing.</p>

<p>This gets more complicated with agents because now the model can call other APIs as part of the workflow.  Taking a sports registration application as an example, imagine someone asking:</p>

<pre><code class="language-text">"Refund the registration for Team A"
</code></pre>

<p>The actual operation could become:</p>

<pre><code class="language-text">Find Team  
  ↓
Find Registration  
  ↓
Find Payment  
  ↓
Stripe  
  ↓
Update Registration  
  ↓
Send Confirmation  
</code></pre>

<p>At that point OpenAI is only one dependency.  MongoDB, authentication, Stripe, your own APIs and whatever you're using for email all have to work correctly too.</p>

<p>I would also be very careful about what decisions the model is actually allowed to make.  Finding a payment is one thing.  Deciding whether the user has permission to refund it or how much they're allowed to refund should still come from the application.</p>

<h2 id="latency">Latency</h2>

<p>AI can be slow.  Most normal API endpoints I've worked with are measured in milliseconds and if one consistently takes multiple seconds I would normally consider that a performance problem.  With an AI request multiple seconds can be completely normal, and once you add retrieval and tool calls the request can easily get much longer.</p>

<p>This is where queues, Redis, Kafka and workers become much more useful.</p>

<p>Instead of keeping this open:</p>

<pre><code class="language-text">POST /generate

...wait...

...wait...

200 OK  
</code></pre>

<p>we can do something closer to:</p>

<pre><code class="language-text">POST /generate

202 Accepted  
jobId: abc123  
</code></pre>

<p>and let the worker handle:</p>

<pre><code class="language-text">retrieve context  
→ AI
→ call API
→ AI again
→ validate
→ save
</code></pre>

<p>I've built distributed job systems using Redis and have also used Kafka for event driven systems, and AI workloads feel like a pretty natural extension of those patterns.  Once an AI operation starts making multiple calls it's really not just a request anymore, it's a workflow.</p>

<p>There are of course cases where keeping the request open makes sense.  Chat is an obvious one since the response can be streamed and the user expects to see it generated.  I just wouldn't design every AI operation like chat.</p>

<h2 id="costispartoftheapplication">Cost Is Part of the Application</h2>

<p>Cost is another dependency that I didn't really think about in the same way before AI.</p>

<p>If one of my traditional APIs suddenly gets 100x the traffic, I'm looking at CPU, memory, database usage, bandwidth and potentially adding more servers.  With AI every request can also have a direct inference cost.</p>

<p>Something as simple as sending unnecessary context can get expensive:</p>

<pre><code class="language-text">requests × tokens × model cost  
</code></pre>

<p>If a feature is called 10,000 times and we're sending a huge document to the most expensive model every time, the feature can technically be working perfectly while still being a production problem.</p>

<p>This is one place where some pretty boring application optimizations become valuable again.  Cache responses when it makes sense, don't send context you don't need, rate limit expensive functionality and don't use the most expensive model when a smaller model can do the job.</p>

<p>I've used Redis for years primarily to improve application and API performance.  With AI the same cache can potentially improve response time and actually save money at the same time, which makes the tradeoff a little easier to justify.</p>

<h2 id="keepdeterministiccodewhereitmatters">Keep Deterministic Code Where It Matters</h2>

<p>Even if AI is involved in a workflow I still want normal application code to own the important business rules.</p>

<p>For example, AI could extract:</p>

<pre><code class="language-json">{
  "playerName": "John Smith",
  "division": "Mens 4.0",
  "payment": 150
}
</code></pre>

<p>from a registration form or uploaded document.  That's a great use case because extracting inconsistent human input is something AI is good at.</p>

<p>I don't want the model deciding whether $150 is the correct price though.  The registration system already knows the price and that should remain the source of truth.</p>

<p>I would handle it more like:</p>

<pre><code class="language-text">AI extracts information  
    ↓
Validate schema  
    ↓
Load application data  
    ↓
Apply business rules  
    ↓
Perform action  
</code></pre>

<p>This is especially important around payments, permissions, authentication and destructive operations.  I've worked with Stripe payments and ACL/permission systems and I wouldn't replace those rules with a prompt asking the model if a user is allowed to do something.</p>

<p>There's also another dependency here that isn't technical: the user.</p>

<p>Users misspell things, upload the wrong file, paste an entire email into an input, provide contradictory instructions and sometimes ask the AI to do something completely unrelated to the feature.  With a normal form we can control most inputs with selects, checkboxes and validation.  Once we give someone natural language input the number of possible inputs basically explodes.</p>

<p>The backend still needs to assume the input is wrong until it's validated.</p>

<h2 id="monitoringai">Monitoring AI</h2>

<p>Normal application monitoring tells me a lot about whether the application is healthy.  I've used Sentry for production errors and have built monitoring around APIs, background jobs and application performance.</p>

<p>AI adds an unusual problem because everything can technically succeed and the feature can still fail.</p>

<p>For example:</p>

<pre><code class="language-text">OpenAI: 200  
Latency: 2.4 seconds  
Database: success  
Exceptions: 0  
</code></pre>

<p>Everything is green, but if the model tells the user the tournament is March 17 when it's actually March 18, the feature didn't work.</p>

<p>So on top of the normal metrics I think we need to start storing things like which model was used, prompt version, token usage, cost, latency, retries and validation failures.  For important AI features it also makes sense to have a set of examples where we know what a good result looks like and run those again when prompts or models change.</p>

<p>We've always monitored whether a service is up.  With AI we also need some way of determining whether it's actually doing a good job.</p>

<h2 id="conclusion">Conclusion</h2>

<p>The funny part is most of the architecture around reliable AI applications isn't really new.  Queues, Redis, Kafka, workers, retries, caching, rate limiting, monitoring, validation and fallback logic are all things we've already been using.</p>

<p>What's different is the thing in the middle is slower, non-deterministic, can be relatively expensive and accepts almost unlimited forms of user input.  That puts more pressure on all of the boring infrastructure around it.</p>

<p>The AI model gets most of the attention, but I'm starting to think the reliability of an AI feature is going to depend much more on everything we build around the model.</p>]]></content:encoded></item><item><title><![CDATA[Exploring Next.js 13: App Router and Best Practices]]></title><description><![CDATA[<p>I've been using Next.js for awhile now especially for applications where SEO, server-side rendering and performance are important.  Next.js 13 introduced one of the bigger changes I've seen to the framework with the App Router and React Server Components.</p>

<p>Conceptually I really like the direction.  Being able to</p>]]></description><link>https://takuu.me/exploring-next-js-13-app-router-and-best-practices/</link><guid isPermaLink="false">a3f9a536-524e-4262-92ca-8b4017e2a623</guid><dc:creator><![CDATA[Taku Uechi]]></dc:creator><pubDate>Wed, 21 Jun 2023 21:58:00 GMT</pubDate><content:encoded><![CDATA[<p>I've been using Next.js for awhile now especially for applications where SEO, server-side rendering and performance are important.  Next.js 13 introduced one of the bigger changes I've seen to the framework with the App Router and React Server Components.</p>

<p>Conceptually I really like the direction.  Being able to make components server components by default and only push Javascript to the client where it's actually needed makes a lot of sense.  At the same time I started using the App Router fairly early and ran into enough issues where I would still proceed with some caution, especially if you aren't deploying to Vercel.</p>

<p>Here are some of the issues I've run into so far.</p>

<h2 id="prismaandserverless">Prisma and Serverless</h2>

<p>One of the first things to be careful with is Prisma and database connections when running Next.js in a serverless environment.</p>

<p>Coming from a more traditional Node.js/Express application, I'm used to having a long running server with a database connection pool.  Serverless changes that because the application can start multiple instances and each one can potentially create its own database connections.</p>

<p>This becomes really easy to overlook with the App Router because you can query the database directly from a Server Component.</p>

<pre><code class="language-typescript">export default async function Users() {  
  const users = await prisma.user.findMany();

  return (
    &lt;div&gt;
      {users.map(user =&gt; (
        &lt;div key={user.id}&gt;{user.name}&lt;/div&gt;
      ))}
    &lt;/div&gt;
  );
}
</code></pre>

<p>I actually really like being able to do this.  There is much less boilerplate than creating an API endpoint just so the frontend can turn around and call it, but it also makes it easy to forget that the component is now doing backend work and has all of the same concerns as any other backend application.</p>

<p>If the application scales to a bunch of serverless instances you need to make sure your database can handle the connection behavior.  This isn't specifically a Next.js problem but Next.js makes it extremely easy to run into.</p>

<h2 id="cloudflarepages">Cloudflare Pages</h2>

<p>Another issue I ran into was deploying Next.js to Cloudflare Pages.</p>

<p>Vercel obviously gets first class support for new Next.js features, but other platforms don't always support everything immediately.  This was more noticeable with the App Router because there were a lot of new features being released at once.</p>

<p>Things like Server Components, Middleware, Route Handlers, SSR and the Edge Runtime may work differently depending on where you're hosting the application.</p>

<p>I've used Cloudflare quite a bit and like the platform, so my preference isn't automatically to move something to Vercel just because it's using Next.js.  But it does mean I check compatibility before depending too heavily on a newer Next.js feature.</p>

<p>This is something I didn't think about as much with older versions of Next.js.  A feature being supported by Next.js doesn't necessarily mean that feature is supported exactly the same way by the platform you deploy it to.</p>

<h2 id="serverandclientcomponents">Server and Client Components</h2>

<p>Probably the biggest adjustment with the App Router was getting used to where the server/client boundary should be.</p>

<p>By default components are Server Components, which is great until you start using a React library that expects things like state, context or browser APIs.</p>

<p>For example something like Material UI generally needs to run on the client:</p>

<pre><code class="language-tsx">"use client";

import { Button } from "@mui/material";

export default function MyButton() {  
  return &lt;Button&gt;Click Me&lt;/Button&gt;;
}
</code></pre>

<p>Initially it's pretty tempting to just start adding <code>"use client"</code> whenever something doesn't work.  That fixes the immediate problem but you can eventually end up making a huge portion of the application client-side again, which starts defeating one of the reasons for using Server Components in the first place.</p>

<p>I've found it better to push <code>"use client"</code> as far down the component tree as possible.</p>

<p>For example instead of:</p>

<pre><code class="language-text">Product Page (client)  
  Product Details
  Product Images
  Reviews
  Add To Cart
</code></pre>

<p>I would rather have:</p>

<pre><code class="language-text">Product Page (server)  
  Product Details (server)
  Product Images (server)
  Reviews (server)
  Add To Cart (client)
</code></pre>

<p>The <code>Add To Cart</code> component actually needs state and user interaction, while most of the rest of the product page doesn't.</p>

<p>This also seems like a good pattern for ecommerce since product pages are exactly where SEO and initial page performance matter.</p>

<h2 id="dontmoveeverythingtotheserver">Don't Move Everything to the Server</h2>

<p>One thing I don't agree with is treating Server Components as meaning everything should now move to the server.</p>

<p>There is still plenty of functionality that makes more sense in the browser.  Form interactions, autocomplete, modals, filters, drag/drop, realtime updates and other highly interactive functionality probably isn't improved by trying to force it into a Server Component.</p>

<p>I think the better way to look at the App Router is that we finally have more control over where code runs.</p>

<p>Before, a lot of React applications basically started with:</p>

<pre><code class="language-text">Everything runs in the browser  
</code></pre>

<p>and then we added SSR where needed.</p>

<p>The App Router feels closer to:</p>

<pre><code class="language-text">Run everything on the server  
until there is a reason for it to run in the browser  
</code></pre>

<p>I like this mental model much better.</p>

<h2 id="conclusion">Conclusion</h2>

<p>Overall I think the App Router is the right direction for Next.js and React.  Being able to fetch data directly on the server, reduce Javascript sent to the browser and decide exactly where client-side behavior starts is a big improvement.</p>

<p>At least when I first started using it though, I wouldn't migrate an application just because the App Router was the newest way of doing things.  Prisma/serverless connections, hosting compatibility and third-party React libraries were all things I ran into that required more thought than they did with the Pages Router.</p>

<p>Most of those aren't reasons not to use it.  They're just things I would want to figure out early instead of discovering them after the application is already in production.</p>]]></content:encoded></item><item><title><![CDATA[Immutable.js, the 80/20 Rule for React and Redux]]></title><description><![CDATA[<p>I've scoured the internet for some basic information on Immutable.js to help with the performance on some of my React applications.  But most only cover some of the basics or examples that don't use data structures that are common in most API.</p>

<p>Luckily for most coming from a functional</p>]]></description><link>https://takuu.me/immutable-js-the-80-20-rule-for-react-and-redux/</link><guid isPermaLink="false">2d33845f-a61b-49ed-91e1-738cc4bad938</guid><dc:creator><![CDATA[Taku Uechi]]></dc:creator><pubDate>Sun, 25 Feb 2018 02:04:23 GMT</pubDate><content:encoded><![CDATA[<p>I've scoured the internet for some basic information on Immutable.js to help with the performance on some of my React applications.  But most only cover some of the basics or examples that don't use data structures that are common in most API.</p>

<p>Luckily for most coming from a functional programming background, (in JS, those familiar with lodash or underscore) the conceptual mental models and DSL's are relatively the same in Immutable.js.</p>

<p>First we have to understand the two main data structures: Map and List</p>

<h5 id="map">Map</h5>

<pre><code class="language-javascript">const map = Immutable.Map({ id: 1, name: 'John' });  
map.get('name') == 'John'; // true  
map.set('name', 'Mike');  
map.get('name') == 'Mike'; // true  
</code></pre>

<h5 id="list">List</h5>

<pre><code class="language-javascript">const list = Immutable.List([5, 20, 101];  
list.get(1) == 20; // true  
list.set(0, 9);  
list.get(0) == 9; // true  
list.set(4, 30);  
list.toJS(); // [9, 20, 101, undefined, 30]  
</code></pre>

<p>Converting to Immutable.js, fromJS magically detects the proper data structure to convert to.  In this example, Immutable.js knows to create a <strong>List</strong> of <strong>Map</strong> from an Array of Objects.  </p>

<pre><code class="language-javascript">const data = [ { id: 1, name: "John" }, { id: 2, name: "Adam" } ];  
const magic = Immutable.fromJS(data);

Immutable.List.isList(magic); // true  
Immutable.Map.isMap(magic.get(0)); // true
</code></pre>

<p>Of course, this can done manually as shown below</p>

<pre><code class="language-javascript">const result = [ { id: 1, name: "John" }, { id: 2, name: "Adam" } ];

const magic = Immutable.fromJS(result);

let list = Immutable.List();  
result.map((item, index) =&gt; { list = list.set(index, Immutable.Map(item))});  
Immutable.is(list, magic); // true,  
</code></pre>

<p>Okay, with these basic data structure building blocks, lets build a basic redux store using Immutable.js</p>

<p>Let's take a look at this Person reducer using <strong>List</strong> and <strong>Map</strong>  </p>

<pre><code class="language-javascript">const initialState = Immutable.List([  
  Immutable.Map({ id: 1, name: "John Snow", title: "King of the North" }), 
  Immutable.Map({ id: 2, name: "Adam", title: "Butcher" })
]);
function personReducer(state = initialState, action) {  
  switch (action.type) {
    case FETCH_ALL_PEOPLE:  // O(n)
      action.payload.map((item, index) =&gt; { 
        state = state.set(index, Immutable.Map(item));
      });
      // OR state = Immutable.fromJS(action.payload);
      return state;
    case FETCH_ALL_KINGS: // O(n^2)
      action.payload.map((king, index) =&gt; {
        const index = state.findIndex((item) =&gt; {
          return item.get('id') === king.id;
        });
        if ( index &gt;= 0 ) {
          state = state.set(index, Immutable.Map(king));
        } else {
          state.push(Immutable.Map(king));
        }
      });
      return state;
    case CREATE_PERSON: // O(1)
      return state.push(Immutable.Map(action.payload));
    case GET_PERSON: // O(n)
      const index = state.findIndex((item) =&gt; {
        return item.get('id') === action.payload.id;
      });
      if ( index &gt;= 0 ) {
        return state.update(index, (person) =&gt; {
          return person.set('name', action.payload.name);
        });
      } else {
        state.push(Immutable.Map(action.payload));
      }
      return state;
    case DELETE_PERSON: // O(n)
      const index = state.findIndex((item) =&gt; {
        return item.get('id') === action.payload.id;
      });
      return state.delete(index);
    case UPDATE_PERSON: // O(n)
      const index = state.findIndex((item) =&gt; {
        return item.get('id') === action.payload.id;
      });
      if ( index &gt;= 0 ) {
        state = state.set(index, Immutable.Map(action.payload));
      }
      return state;
    default:
      return state;
  }
}
</code></pre>

<p>Things are okay here except when we <code>FETCH_ALL_KINGS</code> and get O(n^2) by trying to combine an Array with a <strong>List</strong>.  We also have the following sprinkled in the code to check for duplicates which makes those cases a minimum of O(n) complexity</p>

<pre><code class="language-javascript">const index = state.findIndex((item) =&gt; {  
  return item.get('id') === action.payload.id;
});
</code></pre>

<h5 id="set">Set</h5>

<p><strong>Set</strong> duplicate checks are done very efficiently.  Lets rewrite the above code using <strong>Set</strong> instead of <strong>List</strong></p>

<pre><code class="language-javascript">const initialState = Immutable.Set([  
  Immutable.Map({ id: 1, name: "John Snow", title: "King of the North" }), 
  Immutable.Map({ id: 2, name: "Adam", title: "Butcher" })
]);
function personReducer(state = initialState, action) {  
  switch (action.type) {
    case FETCH_ALL_PEOPLE:  // O(nlogn)
    case FETCH_ALL_KINGS:  // O(nlogn)
      action.payload.map((item, index) =&gt; { 
        state = state.add(Immutable.Map(item));
      });
      return state;
    case CREATE_PERSON: // O(logn)
    case GET_PERSON: // O(logn)
      return state.add(Immutable.Map(action.payload));
    case DELETE_PERSON: // O(n)
      return state.delete(Immutable.Map(action.payload));
    case UPDATE_PERSON: // O(n)
      // This is a combo of DELETE_PERSON then CREATE_PERSON
      const found = state.find((person) =&gt; {
        return action.payload.id == person.get('id');
      });
      if (found) {
       state = state.delete(Immutable.Map(found));
       state = state.add(Immutable.Map(action.payload));
      }
      return state;
    default:
      return state;
  }
}
</code></pre>

<p>The code <code>state.add(Immutable.Map(action.payload));</code> checks for duplicates and if it does't exist, it adds it to the <strong>Set</strong>.  Similarly, <code>state.delete(Immutable.Map(action.payload))</code> is able to find the same data objects and delete it properly.</p>

<p>With this, you'll notice that the worse efficiency is at O(nlogn) which is a great trade off vs O(n^2).  The code is also more clean and readable.  A drawback of <strong>Set</strong> is that it isn't ordered like <strong>List</strong> so if order isn't important, the tradeoffs are worth it.</p>

<h5 id="record">Record</h5>

<p>If you noticed with <strong>Map</strong> <code>person.get('name')</code> isn't nearly as elegant as <code>person.name</code> in vanilla javascript on top of also losing a lot of the object syntactic sugar ES6+ provides.  Luckily Immutable.js provides the data structure <strong>Record</strong>, which is essentially <strong>Map</strong> but can be treated like a javascript object</p>

<pre><code class="language-javascript">const Person = Immutable.Record({ id: "", name: "" });  
const person = new Person({ id: 1, name: "John Snow" });

person.name // "John Snow"  
const { name } = person;  // name = "John Snow"  
</code></pre>

<p>We just covered the basics of <strong>Map</strong>, <strong>List</strong>, <strong>Set</strong> and <strong>Record</strong>. These data structures is just the tip of the iceberg but should be a great starting point for Immutable.js</p>]]></content:encoded></item><item><title><![CDATA[Using Functional Programming in JavaScript]]></title><description><![CDATA[<p>I've been looking more into functional programming lately and how some of the concepts can be applied to Javascript.  I'm definitely not talking about converting everything to Haskell or writing Javascript completely differently, but there are some ideas that I think can make larger applications much easier to work with.</p>]]></description><link>https://takuu.me/using-functional-programming-in-javascript/</link><guid isPermaLink="false">b2f0e6ce-f310-491d-97d4-a88bed0a6772</guid><dc:creator><![CDATA[Taku Uechi]]></dc:creator><pubDate>Sun, 02 Jul 2017 16:34:00 GMT</pubDate><content:encoded><![CDATA[<p>I've been looking more into functional programming lately and how some of the concepts can be applied to Javascript.  I'm definitely not talking about converting everything to Haskell or writing Javascript completely differently, but there are some ideas that I think can make larger applications much easier to work with.</p>

<p>A lot of these concepts are already pretty common in Javascript especially if you've used libraries like lodash, underscore, Immutable.js or even just methods like <code>map</code>, <code>filter</code> and <code>reduce</code>.</p>

<h2 id="nosideeffects">No Side Effects</h2>

<p>One of the main concepts in functional programming is avoiding side effects.  Basically given the same input, a function should return the same output without changing something outside of the function.</p>

<p>Instead of something like:</p>

<pre><code class="language-javascript">let total = 0;

function add(value) {  
  total += value;
}
</code></pre>

<p>we can do:</p>

<pre><code class="language-javascript">function add(total, value) {  
  return total + value;
}
</code></pre>

<p>The second function is much easier to follow because everything it needs is passed into it.  We don't have to search somewhere else in the application to figure out who changed <code>total</code>, when it changed or what the current value is.</p>

<p>This sounds pretty basic but as an application grows and more things start changing the same state, figuring out what changed something can get difficult very quickly.</p>

<h2 id="lessstate">Less State</h2>

<p>State is obviously unavoidable in an application.  We need to store users, application settings, API responses and basically everything else the application needs to remember.  The problem isn't really state itself but having too many places that can modify the same state.</p>

<p>For example instead of modifying an object directly:</p>

<pre><code class="language-javascript">user.name = "Taku";  
</code></pre>

<p>we can create a new object:</p>

<pre><code class="language-javascript">const updatedUser = {  
  ...user,
  name: "Taku"
};
</code></pre>

<p>Now we still have the original <code>user</code> object and we know exactly where the new object came from.  This type of pattern becomes especially useful when working with Redux where we don't want reducers modifying the existing state.</p>

<h2 id="concurrency">Concurrency</h2>

<p>Another interesting benefit is concurrency.  Javascript in the browser is mostly single threaded but we already deal with a lot of asynchronous operations.</p>

<pre><code class="language-javascript">Promise.all([  
  getUsers(),
  getProducts(),
  getOrders()
]);
</code></pre>

<p>If these functions all depend on or modify some shared state, it becomes much easier to get unexpected results.  On the other hand a function like:</p>

<pre><code class="language-javascript">function calculateTotal(items) {  
  return items.reduce((total, item) =&gt; {
    return total + item.price;
  }, 0);
}
</code></pre>

<p>doesn't really care what else the application is doing.  We can call it whenever we want with the same data and should always get the same result.</p>

<p>I think this becomes more important as Javascript applications start doing more things asynchronously and potentially in parallel.</p>

<h2 id="testing">Testing</h2>

<p>Pure functions also make testing a lot easier.</p>

<pre><code class="language-javascript">function multiply(a, b) {  
  return a * b;
}
</code></pre>

<p>There isn't much setup needed to test this.</p>

<pre><code class="language-javascript">multiply(2, 3) === 6;  
</code></pre>

<p>We don't need a database, browser, global variables or some complicated application state before running the test.  Obviously an entire application can't be written this way since we still need I/O, APIs and databases, but separating as much of the business logic as possible into these types of functions makes testing much easier.</p>

<h2 id="reusingcodebetweenfrontendandbackend">Reusing Code Between Frontend and Backend</h2>

<p>This also works pretty well with isomorphic Javascript.  If some of our Javascript is going to run on both the frontend and backend, it helps if the actual business logic isn't tightly coupled to either environment.</p>

<pre><code class="language-javascript">function calculateDiscount(price, percentage) {  
  return price - price * percentage;
}
</code></pre>

<p>There is nothing browser or Node specific about the above function.  It can run on the frontend, backend or inside a test.</p>

<p>I think there is a lot of value in keeping business logic like this separate from the code responsible for actually getting or saving the data.</p>

<h2 id="composition">Composition</h2>

<p>Another useful concept is building larger functionality by combining smaller functions.</p>

<pre><code class="language-javascript">function double(value) {  
  return value * 2;
}

function addTen(value) {  
  return value + 10;
}

function calculate(value) {  
  return addTen(double(value));
}
</code></pre>

<p>Each function is really simple by itself and we can test each one separately.  More complicated functionality can then be built by combining these smaller functions instead of having one huge function managing a bunch of variables and state.</p>

<h2 id="javascriptisalreadyprettyfunctional">Javascript Is Already Pretty Functional</h2>

<p>The nice thing is Javascript already gives us a lot of tools for doing this.</p>

<pre><code class="language-javascript">const activeUsers = users  
  .filter(user =&gt; user.active)
  .map(user =&gt; user.name);
</code></pre>

<p>Instead of manually creating an array, looping through <code>users</code>, checking each user and pushing the name into another array, we describe the transformations we want to make to the data.</p>

<p>Obviously I don't think Javascript applications need to be 100% functional.  Applications have state, perform I/O, call APIs and save things into databases so side effects are going to happen.</p>

<p>But minimizing shared state, using pure functions where it makes sense and separating business logic from I/O seems like a good way to make larger Javascript applications easier to maintain.</p>]]></content:encoded></item><item><title><![CDATA[Some simple AI]]></title><description><![CDATA[<p>I've seen some impressive demonstrations of machine learning and am definitely not claiming this as one.  But I'm pretty proud of a kid I've been tutoring for a quite sometime now.</p>

<p>We created a simple simulation where a "muncher" would randomly move either left, right or jump to eat the</p>]]></description><link>https://takuu.me/some-simple-machine-learning-2/</link><guid isPermaLink="false">ce42356e-0578-4c28-8b33-3448d9b8ee93</guid><dc:creator><![CDATA[Taku Uechi]]></dc:creator><pubDate>Wed, 01 Jun 2016 23:09:16 GMT</pubDate><content:encoded><![CDATA[<p>I've seen some impressive demonstrations of machine learning and am definitely not claiming this as one.  But I'm pretty proud of a kid I've been tutoring for a quite sometime now.</p>

<p>We created a simple simulation where a "muncher" would randomly move either left, right or jump to eat the randomly placed falling food.  Through many iterations, the muncher would figure out the most efficient way to eat the most amount of food.</p>

<p>In the beginning, the muncher would aimlessly move around as shown below (muncher is the green dot, food is the falling blue dot):</p>

<iframe width="560" height="315" src="https://www.youtube.com/embed/BttWhfkG1B0" frameborder="0" allowfullscreen></iframe>

<p>But after sometime, the muncher started to figure out a more efficient way to get more and more food:</p>

<iframe width="560" height="315" src="https://www.youtube.com/embed/OoZfRQuXEAw" frameborder="0" allowfullscreen></iframe>]]></content:encoded></item><item><title><![CDATA[Share data models in Mongoose with your Frontend]]></title><description><![CDATA[<p>In order to share a data models between technologies (ex: backend and frontend), the languages need to interpret the data to a common format.  Most of the time, this boils down to converting/extacting a JSON object model.</p>

<p>Example of a shared JSON between the backend and frontend:  </p>

<pre><code>// file: shared/</code></pre>]]></description><link>https://takuu.me/share-data-models-throughout-your-application/</link><guid isPermaLink="false">c0e2cfce-5a41-4382-936d-fa2d830466d4</guid><dc:creator><![CDATA[Taku Uechi]]></dc:creator><pubDate>Sat, 19 Mar 2016 20:46:04 GMT</pubDate><content:encoded><![CDATA[<p>In order to share a data models between technologies (ex: backend and frontend), the languages need to interpret the data to a common format.  Most of the time, this boils down to converting/extacting a JSON object model.</p>

<p>Example of a shared JSON between the backend and frontend:  </p>

<pre><code>// file: shared/models/player.js
var Player {  
  league: { type: 'id', ref: 'League' },
  division: { type: 'id', ref: 'Division' },
  team: { type: 'id', ref: 'Team' },
  name: { type: 'string', default: '' },  
  created: { type: 'date', default: Date.now },
  updated: { type: 'date', default: Date.now }
};
export default Player;  
</code></pre>

<p>In case if you didn't notice, this looks exceptional similar to a Mongoose Schema Model.  The main difference is the ObjectId is replaced with the string 'id' and all the other types are now relagated to strings too for consistency:</p>

<pre><code>// file: api/utils.js
import mongoose from 'mongoose';  
var Schema = mongoose.Schema;  
import _ from 'lodash';

let mongooseify = function(json) {

  let result = {};
  _.map(Object.keys(json), (key) =&gt; {
    let property = _.cloneDeep(json[key]);
    let type;
    switch(property.type) {
      case 'id':
        type = Schema.ObjectId;
        break;
      case 'number':
        type = Number;
        break;
      case 'string':
        type = String;
        break;
      case 'date':
        type = Date;
        break;
      default:
        break;
    }
    result[key] = _.assign({}, property, {type});
  });

  return result;
};
</code></pre>

<p>Note: (This can be extended to add additional types) <br>
And finally, create the Mongoose Model:</p>

<pre><code class="language- javascript">// file: api/models/player.model.js
'use strict';  
import mongoose from 'mongoose';  
var Schema = mongoose.Schema;  
import player from '../../shared/models/player';  
import utils from '../utils';

/**
 * Player Schema
 */
var PlayerSchema = new Schema(utils.mongooseify(player));

module.exports = mongoose.model('Player', PlayerSchema);
</code></pre>]]></content:encoded></item><item><title><![CDATA[Remove duplicates from MongoDB]]></title><description><![CDATA[<p>As of version 2.x, MongoDB dropped support for dropDups due to it's dangerous nature of not knowing which item to remove (We don't want to break the dependency chain do we?)</p>

<p>Given the simple object of a Sports Team  </p>

<pre><code>{
  "name": "Knights",
  "city": "Los Angeles",
  "state": "CA"
}
</code></pre>

<p>We want to</p>]]></description><link>https://takuu.me/remove-duplicates-from-mongodb/</link><guid isPermaLink="false">255e9c80-f409-4ea2-892e-2fe9dd3da49b</guid><dc:creator><![CDATA[Taku Uechi]]></dc:creator><pubDate>Wed, 09 Mar 2016 17:31:21 GMT</pubDate><content:encoded><![CDATA[<p>As of version 2.x, MongoDB dropped support for dropDups due to it's dangerous nature of not knowing which item to remove (We don't want to break the dependency chain do we?)</p>

<p>Given the simple object of a Sports Team  </p>

<pre><code>{
  "name": "Knights",
  "city": "Los Angeles",
  "state": "CA"
}
</code></pre>

<p>We want to remove all duplicates that have the same combination of name, city and state.  To view all duplicates of this combination, run a map reduce in MongoDB:</p>

<pre><code>db.getCollection('teams').aggregate(  
    { $match: { 
        name: { $ne: ''},
        city: { $ne: ''},
        state: { $ne: ''}
    }},
    { $group: {
        _id: { name: "$name", city: "$city", state: "$state"},
        count: { $sum: 1},
        dups: { $push: "$_id"}
    }},
    { $match: {
        count: { $gt: 1}
    }}
)
</code></pre>

<p>The results should show if there are any duplicate combinations.</p>

<p>To remove the duplicates run:  </p>

<pre><code>var duplicates = [];

db.getCollection('teams').aggregate([  
  { $match: { 
      name: { $ne: ''},
      city: { $ne: ''},
      state: { $ne: ''}
  }},
  { $group: { 
      _id: { name: "$name", city: "$city", state: "$state"},
      count: { $sum: 1},
      dups: { $push: "$_id"}, 

  }}, 
  { $match: { 
      count: { $gt: 1}
  }}
])               
.forEach(function(doc) {
    doc.dups.shift();      
    doc.dups.forEach( function(dupId){ 
        duplicates.push(dupId);
        }
    )    
})


db.getCollection('teams').remove({_id:{$in:duplicates}})  
</code></pre>

<p>A caution to note, this script does not check the dependencies before deleting.  So use at your own risk.</p>]]></content:encoded></item><item><title><![CDATA[The Problem with async await with Lodash]]></title><description><![CDATA[<p>I recently was writing a web scraper and ran into an issue with async await.  It's not so much a problem with how it works.  In fact I love the new ES2016/ES7 proposal.  It's just the current tools and libraries will need to adapt to work in parallel with</p>]]></description><link>https://takuu.me/the-problem-with-async-await/</link><guid isPermaLink="false">1df9f1a8-7460-41cb-8caf-e567fa2c2915</guid><dc:creator><![CDATA[Taku Uechi]]></dc:creator><pubDate>Mon, 29 Feb 2016 17:20:40 GMT</pubDate><content:encoded><![CDATA[<p>I recently was writing a web scraper and ran into an issue with async await.  It's not so much a problem with how it works.  In fact I love the new ES2016/ES7 proposal.  It's just the current tools and libraries will need to adapt to work in parallel with it.  Working with Lodash with async await is just not feasible at the moment.</p>

<p>Fetching for a list of teams then fetching for their list of players returns a list of promises in the below example:</p>

<pre><code class="language-javascript">async function getTeams() {  
  var teamList = _.map(await getTeamList(), async (team) =&gt; {
    team.players = await getPlayerList(team.teamId);
  });

  return teamList;
}

getTeams().then((data)=&gt; {  
  console.log('Array of promises...', data);
});
</code></pre>

<p>This isn't too surprising since async functions returns a promise and mapping through them simple just returns the list of them.  But the problem lies in the way Lodash/Underscore implements iterating through lists.  If you need to run an await, it needs to be inside an async function and cannot be inside a normal function(or arrow function for that matter).  So iterating through a list and handling promises through a callback function becomes much more of an issue.</p>

<p>The best way I found to handle this issue to to iterate without callback functions using the old school For Loops.</p>

<pre><code class="language-javascript">async function getTeams() {  
  var teamList = await getTeamList();
  for(let i=0; i&lt;teamList.length; i++) {
    let team = teamList[i];
    team.players = await getPlayerList(team.teamId);
  }
  return teamList;
}

getTeams().then((data)=&gt; {  
  console.log('Array of teams with players!', data);
});
</code></pre>]]></content:encoded></item><item><title><![CDATA[Creating unit tests in AngularJS]]></title><description><![CDATA[<p>Unit testing can be one of the most disliked part of the software development.  John Papa came forward and stated that he dislikes writing tests because of the amount of setup required to write the first "it" (source: <a href="http://devchat.tv/adventures-in-angular/025-aia-testing-with-ward-bell">http://devchat.tv/adventures-in-angular/025-aia-testing-with-ward-bell</a>).  I can definitely relate and I figure</p>]]></description><link>https://takuu.me/creating-unit-tests-in-angularjs/</link><guid isPermaLink="false">a1156509-3dc3-4c64-871c-316d672d309d</guid><dc:creator><![CDATA[Taku Uechi]]></dc:creator><pubDate>Tue, 03 Mar 2015 05:40:38 GMT</pubDate><content:encoded><![CDATA[<p>Unit testing can be one of the most disliked part of the software development.  John Papa came forward and stated that he dislikes writing tests because of the amount of setup required to write the first "it" (source: <a href="http://devchat.tv/adventures-in-angular/025-aia-testing-with-ward-bell">http://devchat.tv/adventures-in-angular/025-aia-testing-with-ward-bell</a>).  I can definitely relate and I figure I should share some tips <br>
to reduce the boilerplate for writing tests.</p>

<p><strong>Why we should</strong></p>

<p>Writing tests help write more testable code which usually translates to more simple code and allows for easier refactoring.  It also instills confidence in the developers to deploy their code that are unit tested.</p>

<ul>
<li><p>Reduce time to first "it"</p></li>
<li><p>Maintainability</p></li>
<li><p>Readability while being more declarative instead of imperative</p></li>
</ul>

<p><strong>Tooling</strong></p>

<ul>
<li>Karma</li>
<li>Jasmine</li>
</ul>

<p><strong>Ways to reduce boilerplate</strong></p>

<ul>
<li>if using Jasmine, nested describes helps write clearer tests.  By nesting describes, we can bundle similar tests as
well as bundle similar boilerplate in the beforeEach and write leaner "it" statements. (<a href="http://devchat.tv/adventures-in-angular/026-aia-testing-tools">http://devchat.tv/adventures-in-angular/026-aia-testing-tools</a>)  </li>
<li>reduce mocks (refer to post on TDD is dead?)
<ul><li>Less global states</li>
<li>More modular code</li></ul></li>
<li>automate ways to run tests
<ul><li>karma TDD, by using PhantomJS.  Setup to run on file save.</li></ul></li>
</ul>

<p><strong>Plugins</strong></p>

<ul>
<li>promote ng-html2js</li>
<li>promote your ng-request2js</li>
<li>promote your html-to-json-array</li>
</ul>

<h5 id="testingdirectivesgeneral">Testing directives (general)</h5>

<pre><code class="language-javascript">//directive someDirective
angular.module('someDirective')  
  .directive('someDirective', someDirective);
function someDirective() {  
  return {
    restrict: 'E',
    scope: {
      personName: '='
    },
    template: '&lt;div&gt;{{welcomeMessage}}&lt;/div&gt;',
    link: function(scope, element, attrs) {
      scope.welcomeMessage = 'Hello ' + scope.personName;
    }
  }
};
</code></pre>

<pre><code class="language-javascript">// typical Directive boilerplate should go here
describe('someDirective', function () {  
  beforeEach(module('app'));
  var $scope, $compile, $rootScope, element;

  beforeEach(inject(function($injector) {
    $rootScope = $injector.get('$rootScope');
    $compile = $injector.get('$compile');
    $scope = $rootScope.$new();

    element = angular.element('&lt;some-directive person-name="John"&gt;&lt;/some-directive&gt;');
    $compile(element)($scope);
  }));

  it('should welcome the user', function() {
      expect(element.html()).toContain('Hello John');
  });

});
</code></pre>

<h5 id="testingdirectivescontroller">Testing directives (controller)</h5>

<pre><code class="language-javascript">// directive someDirective
angular.module('app', []);  
angular.module('app')  
  .directive('someDirective', someDirective);

function someDirective() {  
  return {
    restrict: 'E',
    scope: {},
    template: '&lt;div&gt;{{welcomeMessage}}&lt;/div&gt;',
    controller: function($scope) {
      $scope.welcome = function(name) {
        $scope.welcomeMessage = 'Hello ' + name;
      }
    }
  }
}
</code></pre>

<p><strong>test directive controller scope</strong></p>

<pre><code class="language-javascript">describe('someDirective', function () {  
  beforeEach(module('app'));
  var $scope, $compile, $rootScope, element;

  beforeEach(inject(function($injector) {
    $rootScope = $injector.get('$rootScope');
    $compile = $injector.get('$compile');
    $scope = $rootScope.$new();

    element = angular.element('&lt;some-directive &gt;&lt;/some-directive&gt;');
    $compile(element)($scope);
  }));

  it('should welcome the user', function() {
      var scope = element.isolateScope();
      scope.welcome('John');
      $scope.$digest();
      expect(element.html()).toContain('Hello John');
  });
</code></pre>

<p><strong>test directive controller this</strong></p>

<pre><code class="language-javascript">// directive someDirective
angular.module('app', []);  
angular.module('app')  
  .directive('someDirective', someDirective);

function someDirective() {  
  return {
    restrict: 'E',
    scope: {},
    template: '&lt;div&gt;{{welcomeMessage}}&lt;/div&gt;',
    controller: function($scope) {
      this.welcome = function(name) {
        $scope.welcomeMessage = 'Hello ' + name;
      }
    }
  }
};
</code></pre>

<pre><code class="language-javascript">describe('someDirective', function () {  
  beforeEach(module('app'));
  var $scope, $compile, $rootScope, element, controller;

  beforeEach(inject(function($injector) {
    $rootScope = $injector.get('$rootScope');
    $compile = $injector.get('$compile');
    $scope = $rootScope.$new();

    element = angular.element('&lt;some-directive &gt;&lt;/some-directive&gt;');
    $compile(element)($scope);

    $rootScope.$apply();
    controller = element.controller('someDirective');
  }));

  it('should welcome the user', function() {
      controller.welcome('John');
      $scope.$digest();
      expect(element.html()).toContain('Hello John');
  });
</code></pre>

<p><strong>Testing Services</strong></p>

<pre><code class="language-javascript">// someService code here
angular.module('app', []);  
angular.module('app')  
  .factory('someService', someService);

function someService() {  
  var welcomeMessage = '';
  var MessageCreator = function() {
    this.welcome = function(name) {
      welcomeMessage = 'Hello ' + name;
    };

    this.getWelcomeMessage = function() {
      return welcomeMessage;
    };
  }
  return MessageCreator;
};
</code></pre>

<pre><code class="language-javascript">// test code here
describe('someService', function() {  
  beforeEach(module('app'));
  var $rootScope, $scope, $scope;
  beforeEach(inject( function ($injector) {
    $rootScope = $injector.get('$rootScope');
    someService = $injector.get('someService');
    $scope = $rootScope.$new();
  }));

  it('should create new someService object', function() {
    var service = new someService();
    expect(someService).toBeDefined();
    expect(typeof someService).toBe('object');
  });

  it('should create a welcome message', function() {
    var service = new someService();
    service.welcome('John');
    expect(service.getWelcomeMessage()).toEqual('Hello John');
  });
}
</code></pre>

<p><strong>Testing Controllers</strong></p>

<pre><code class="language-javascript">// someController code here

angular.module('app', []);  
angular.module('app')  
  .controller('SomeController', SomeController);
function SomeController($scope) {  
  $scope.welcome = "Welcome " + $scope.name;
}
</code></pre>

<pre><code class="language-javascript">// test code here
describe('someController', function(){  
  beforeEach(module('app'));
  var scope, ctrl;

  beforeEach(inject(function($controller, $rootScope) {
    $cope = $rootScope.$new();
    ctrl = $controller(someController, { $scope: scope });
  }));

  it('should change welcome message when name is set', function() {
    scope.name = "John";
    scope.$digest();
    expect(scope.welcome).toBe("Welcome John");
  });
});
</code></pre>]]></content:encoded></item><item><title><![CDATA[Favorite ES6 Features]]></title><description><![CDATA[<p>With ES6 standardized and popular transpilers like 6to5 making its emergence, I figure to list out some of my favorite ES6 features.</p>

<h4 id="arrowfunction">Arrow Function</h4>

<p>Without a doubt, the arrow function is my favorite and probably one of the most commonly seen peppered around in github source code.  It's pure syntactic</p>]]></description><link>https://takuu.me/favorite-es6-features/</link><guid isPermaLink="false">d7ce35d8-1446-451e-9f31-df3267bb2133</guid><dc:creator><![CDATA[Taku Uechi]]></dc:creator><pubDate>Tue, 10 Feb 2015 07:02:29 GMT</pubDate><content:encoded><![CDATA[<p>With ES6 standardized and popular transpilers like 6to5 making its emergence, I figure to list out some of my favorite ES6 features.</p>

<h4 id="arrowfunction">Arrow Function</h4>

<p>Without a doubt, the arrow function is my favorite and probably one of the most commonly seen peppered around in github source code.  It's pure syntactic sugar but it's simplicity in how it handles the clunkiness of the <code>this</code> keyword definitely makes this my favorite.</p>

<p><strong>Before:</strong></p>

<pre><code class="language-javascript">var User: {  
  name: "John",
  welcome: function() {
    var that = this;
    request.get(url, function(res) {
      that.name = res.name;
    });
  }
}
</code></pre>

<p><strong>With ES6:</strong></p>

<pre><code class="language-javascript">var User: {  
  name: "John",
  welcome: function() {
    request.get(url, res =&gt; this.name = res.name );
  }
}
</code></pre>

<h4 id="promises">Promises</h4>

<p>There's a lot of libraries provide the promises functionality like Q, Bluebird and in AngularJS but I was hoping for a more native implementation to quiet all the naysayers in regards to callback hell.  Finally, that day has come.</p>

<p><strong>Before:</strong></p>

<pre><code class="language-javascript">async1(function () {  
  async2(function () {
    async3(function () {
      async4(function () {
      })
    })
  })
})
</code></pre>

<p><strong>With ES6:</strong></p>

<pre><code class="language-javascript">var async1 = new Promise(function(resolve, reject) {  
  resolve(1);
});
var async2 = new Promise(function(resolve, reject) {  
  resolve(1);
});
var async3 = new Promise(function(resolve, reject) {  
  resolve(1);
});
var async4 = function() {console.log('async4');}

async1.then(nosync).then(async3).then(async4);
</code></pre>

<h4 id="let">Let</h4>

<p>Javascript has an uncanny valley effect for most developers coming from a C and Java background.  It looks like Java but it doesn't behave like it.  Most developers learn the hard way through hard to find bugs.  One of the bugs that get most developers is scoping</p>

<p><strong>Before:</strong></p>

<pre><code class="language-javascript">for(var i=0; i&lt;10; i++) {  
// some implementation
}

console.log(i);  
// 10;
</code></pre>

<p><strong>With ES6:</strong></p>

<pre><code class="language-javascript">for(let i=0; i&lt;10; i++) {  
// some implementation
}

console.log(i);  
// i is not defined
</code></pre>

<h4 id="defaultparameters">Default parameters</h4>

<p>Although I wasn't too fond of CoffeeScript (I prefer TypeScript), one feature I liked a lot about CoffeeScript was the ability to set default parameters.  It was more declarative and reduced some plumbing when passing in parameters.</p>

<p><strong>Before:</strong></p>

<pre><code class="language-javascript">function handler(name, message) {  
  if (typeof name === "undefined") name = "John";
  if (typeof message === "undefined") message = "Hello";

  console.log(message + " " + name);
}
</code></pre>

<p><strong>With ES6:</strong></p>

<pre><code class="language-javascript">function handler(name = "John", message = "Hello") {  
  console.log(message + " " + name);
}
</code></pre>

<h4 id="destructuring">Destructuring</h4>

<p>Once upon a time, I used to write in Perl.  It was bashed for it's archaic and unreadable syntax (Write once, read never!).  But quite honestly, if your developers had enough discipline, you can pump out pretty maintainable code.  One such feature that I missed from Perl was Destructuring.</p>

<p><strong>Before:</strong></p>

<pre><code class="language-javascript">var list = [1,2,3];  
var a = list.shift();  
list.shift();  
var b = list.shift();  
console.log(a,b);  
// 1 3
</code></pre>

<p><strong>With ES6:</strong></p>

<pre><code class="language-javascript">var [a, , b] = [1,2,3];  
console.log(a,b);  
// 1 3
</code></pre>]]></content:encoded></item><item><title><![CDATA[Projects]]></title><description><![CDATA[<p><a href="http://www.famcentric.com">FamCentric</a> [Node, Express, MongoDB, Angular, Bootstrap]</p>

<p>Show and rate schools K through elementary schools as well as language schools.  Site built using the MEAN stack.  Build with a CMS, scraper, OAuth login, search, rating and review features.</p>

<p><a href="https://github.com/tym2/leaguer">Leaguer</a> [Node, Express, MongoDB, React, Reflux, Bootstrap]</p>

<p>Isomorphic web application built with both</p>]]></description><link>https://takuu.me/projects/</link><guid isPermaLink="false">80854feb-b1e4-4d32-b9f1-16b1ff39dfe0</guid><dc:creator><![CDATA[Taku Uechi]]></dc:creator><pubDate>Tue, 20 Jan 2015 03:25:32 GMT</pubDate><content:encoded><![CDATA[<p><a href="http://www.famcentric.com">FamCentric</a> [Node, Express, MongoDB, Angular, Bootstrap]</p>

<p>Show and rate schools K through elementary schools as well as language schools.  Site built using the MEAN stack.  Build with a CMS, scraper, OAuth login, search, rating and review features.</p>

<p><a href="https://github.com/tym2/leaguer">Leaguer</a> [Node, Express, MongoDB, React, Reflux, Bootstrap]</p>

<p>Isomorphic web application built with both server-side rendering and a single page application.  Display player and team trending strengths and other teams weaknesses.</p>

<p><strong>NPM Modules</strong></p>

<p><a href="https://www.npmjs.com/package/html-scripts-to-array">html-scripts-to-array</a></p>

<p>Extracts HTML scripts source links to a JSON array.</p>

<p><a href="https://www.npmjs.com/package/karma-ng-request2js-preprocessor">karma-ng-request2js-preprocessor</a></p>

<p>A Karma plugin. Save AngularJS $http JSON requests to JavaScript</p>]]></content:encoded></item></channel></rss>