Inertia Rails Typescript logo

Inertia Rails Typescript

Organization
inertia-rails
inertia-rails-typescript

TypeScript type safety for Inertia Rails (React, Vue, Svelte): shared props, flash, and errors via InertiaConfig module augmentation in globals.d.ts. Use when setting up TypeScript types, configuring shared props typing, fixing TS2344 or TS2339 errors in Inertia components, or adding new shared data.

Overview

Publisherinertia-rails
Repositoryskills
Skill nameinertia-rails-typescript
Stars
68
Forks
2
Bundled files
Instructions only
LicenseMIT
Links
  • Markdown instructions

    A SKILL.md file the model loads on demand, so it only costs tokens when a request actually matches.

  • Works with any LLM

    AI skills are plain Markdown, not provider-specific code, so this works with GPT, Claude, Gemini, Grok, or a local model.

  • Self-contained

    Everything the model needs lives in the instructions — no extra files to sync.

  • Open source

    Published by inertia-rails on GitHub. Read the source before you install it.

Installation

Install the Inertia Rails Typescript AI skill in TypingMind to use it with any LLM, or drop it into another agent that reads SKILL.md.

1

Install in TypingMind

TypingMind installs a skill straight from its GitHub folder — it reads SKILL.md, bundles the resource files, and stores the result locally.

  1. Open the app and go to Plugins → Skills.
  2. Choose "Install from GitHub".
  3. Paste the skill folder URL below and confirm.
  4. Enable the skill in any chat where you want it available.
Plugins → Skills → Add skill → From GitHub URL, then paste the folder URL and press Continue.
2

Install in another agent

Any agent that reads the Agent Skills format can use this skill — copy the folder into that agent's skills directory.

Claude Code — .claude/skills
git clone --depth 1 https://github.com/inertia-rails/skills.git /tmp/skills
mkdir -p .claude/skills
cp -r /tmp/skills/skills/inertia-rails-typescript .claude/skills/inertia-rails-typescript
Restart Claude Code after copying so it picks up the new skill.

Use it in TypingMind

Enable Inertia Rails Typescript in any TypingMind chat and the model takes it from there. Its name and description sit in the system prompt, and the moment a request matches, the model loads the full instructions itself — you never invoke it by hand, and it costs no tokens until it is actually used.

The model loads Inertia Rails Typescript on its own as soon as a request matches it.

Works with any AI model

AI skills are plain Markdown instructions rather than provider-specific code, so Inertia Rails Typescript is not tied to the model it was written for. Install it once in TypingMind and use it with GPT-5, Claude, Gemini, Grok, DeepSeek, Mistral, Llama, or a local model you run yourself — all on your own API keys.

  • Loaded only when it is needed

    The system prompt carries just the name and description. The instructions are fetched on the first matching request, so an idle skill costs nothing.

  • Switch models mid-chat

    Because the skill is instructions rather than code, changing model does not break it — the next model reads the same SKILL.md.

Skill instructions

This is the SKILL.md content the model loads. Read it before installing — a skill is instructions your model will follow.

Inertia Rails TypeScript Setup

Type-safe shared props, flash, and errors using InertiaConfig module augmentation. Works identically across React, Vue, and Svelte — the globals.d.ts and InertiaConfig setup is the same for all frameworks.

Before adding TypeScript types, ask:

  • Shared props (auth, flash)? → Update SharedProps/FlashData in index.ts — InertiaConfig in globals.d.ts propagates them globally via usePage()
  • Page-specific props?type Props = { ... } in the page file only — never include shared props here

InertiaConfig Module Augmentation

Define shared props type ONCE globally — never in individual page components.

InertiaConfig property names are EXACT — do not rename them:

  • sharedPageProps (NOT sharedProps)
  • flashDataType (NOT flashProps, NOT flashData)
  • errorValueType (NOT errorBag, NOT errorType)
typescript
// app/frontend/types/globals.d.ts
import type { FlashData, SharedProps } from '@/types'

declare module '@inertiajs/core' {
  export interface InertiaConfig {
    sharedPageProps: SharedProps   // EXACT name — auto-typed for usePage().props
    flashDataType: FlashData      // EXACT name — auto-typed for usePage().flash
    errorValueType: string[]      // EXACT name — errors are arrays of strings
  }
}
typescript
// app/frontend/types/index.ts
export interface FlashData {
  notice?: string
  alert?: string
}

export interface SharedProps {
  auth: { user?: { id: number; name: string; email: string } }
}

Convention: Use auth: { user: ... } as the shared props key — this matches the Rails inertia_share community convention ({ auth: { user: current_user } }). The auth namespace separates authentication data from page props, preventing collisions when a page has its own user prop. Do NOT use current_user: or user: as top-level keys — they collide with page-specific props and break the convention that other Inertia skills and examples assume.

BAD vs GOOD Patterns

tsx
// BAD — passing shared props as generics:
// usePage<{ users: User[], auth: AuthData, flash: FlashData }>()

// BAD — extending a SharedProps interface into page props:
// interface Props extends SharedData { users: User[] }

// BAD — declaring PageProps interface:
// interface PageProps { auth: AuthData; flash: FlashData }

// BAD — using current_user or user as top-level shared key:
// interface SharedProps { current_user: User }

// BAD — destructuring auth directly from usePage() (TS2339: 'auth' does not exist on Page):
// const { auth } = usePage()
// usePage() returns a Page object with { props, flash, component, url, ... }
// auth lives inside props, not on the Page itself

// BAD — duplicating InertiaConfig in index.ts (it belongs in globals.d.ts):
// declare module '@inertiajs/core' { ... }  ← in index.ts

// GOOD — props from usePage().props, flash from usePage().flash:
const { props, flash } = usePage()
// props.auth is typed (from SharedProps via InertiaConfig)
// flash.notice is typed (from FlashData via InertiaConfig)

Important: globals.d.ts configures InertiaConfig ONCE. When adding a new shared prop, only update index.ts — do NOT touch globals.d.ts:

typescript
// BEFORE — app/frontend/types/index.ts
export interface SharedProps {
  auth: { user?: { id: number; name: string; email: string } }
}

// AFTER — add the new key here, NOT in globals.d.ts
export interface SharedProps {
  auth: { user?: { id: number; name: string; email: string } }
  notifications: { unread_count: number }
}

InertiaConfig in globals.d.ts references SharedProps by name — it picks up the change automatically. Adding a second declare module '@inertiajs/core' causes conflicts.

Page-Specific Props

Page components type ONLY their own props. Shared props (like auth) and flash come from InertiaConfig automatically.

type vs interface for page props (React-specific)

This constraint applies to React only. Vue's defineProps<T>() and Svelte's $props() do not use usePage<T>() generics, so interface works fine there.

usePage<T>() requires T to have an index signature. type aliases have one implicitly; interface declarations do not. Using interface with usePage causes TS2344 at compile time.

PatternWorks with usePage<T>()?Notes
type Props = { users: User[] }YesPreferred — just works
interface Props { users: User[] }No — TS2344Missing index signature
usePage<Required<Props>>()YesWraps interface to add index signature
tsx
// React
type Props = {
  users: User[]         // page-specific only
  // auth is NOT here — it comes from InertiaConfig globally
}

export default function Index({ users }: Props) {
  // Access shared props separately:
  const { props, flash } = usePage()
  // props.auth is typed via InertiaConfig
  // flash.notice is typed via InertiaConfig
  return <UserList users={users} />
}

Accessing shared props in Vue and Svelte

Vue and Svelte use different patterns to access shared props, but InertiaConfig typing works the same way.

vue
<!-- Vue 3 — usePage() returns reactive object; use computed() for derived values -->
<script setup lang="ts">
import { usePage } from '@inertiajs/vue3'
import { computed } from 'vue'

const page = usePage()
const userName = computed(() => page.props.auth.user?.name) // typed via InertiaConfig
</script>
svelte
<!-- Svelte — page store from @inertiajs/svelte -->
<script lang="ts">
  import { page } from '@inertiajs/svelte'
  // $page.props.auth is typed via InertiaConfig
  // $page.flash.notice is typed via InertiaConfig
</script>

Common TypeScript Errors

ErrorCauseFix
TS2344 on usePage<Props>()interface lacks index signatureUse type Props = { ... } instead of interface, or wrap: usePage<Required<Props>>()
TS2339 'auth' does not exist on type PageDestructuring auth from usePage() directlyusePage() returns { props, flash, ... } — use usePage().props.auth, not usePage().auth
TS2339 'flash' does not exist on typeAccessing usePage().props.flashFlash is top-level: usePage().flash, NOT usePage().props.flash
Shared props untypedMissing InertiaConfigAdd globals.d.ts with module augmentation (see above)
InertiaConfig not taking effectDeclaration in wrong fileMust be in a .d.ts file (e.g., globals.d.ts), not in .ts — TypeScript ignores declare module in regular .ts files that have imports/exports
Types correct but IDE shows errorsglobals.d.ts not includedVerify tsconfig.app.json includes the types directory in include array

Typelizer Integration

If using the typelizer gem (see alba-inertia skill), SharedProps are auto-generated from your serializer — do NOT manually write the SharedProps interface in index.ts. You only write globals.d.ts once (the InertiaConfig augmentation). When you add a new attribute to SharedPropsResource, Typelizer regenerates index.ts and the types propagate via InertiaConfig — no manual type updates needed.

Related Skills

  • Shared props setupinertia-rails-controllers (inertia_share)
  • Flash configinertia-rails-controllers (flash_keys)
  • Auto-generated typesalba-inertia (Typelizer + Alba resources)
  • Page component propsinertia-rails-pages (type Props pattern)

Frequently asked questions

What does the Inertia Rails Typescript AI skill do?

TypeScript type safety for Inertia Rails (React, Vue, Svelte): shared props, flash, and errors via InertiaConfig module augmentation in globals.d.ts. Use when setting up TypeScript types, configuring shared props typing, fixing TS2344 or TS2339 errors in Inertia components, or adding new shared data.

Why use Inertia Rails Typescript on TypingMind?

Because you install it once and use it with any model. Inertia Rails Typescript is plain Markdown rather than provider-specific code, so the same skill runs on GPT-5, Claude, Gemini, Grok, or a local model — and you can switch model mid-chat without it breaking. TypingMind runs on your own API keys, so you pay providers directly instead of a per-seat subscription, and your skills and chats stay in your own storage.

How do I install Inertia Rails Typescript in TypingMind?

Open Plugins → Skills → Install from GitHub in TypingMind and paste https://github.com/inertia-rails/skills/tree/main/skills/inertia-rails-typescript. TypingMind reads its SKILL.md and installs it as a skill you can enable per chat.

Which AI models can use Inertia Rails Typescript?

Any model you connect in TypingMind. AI skills are plain Markdown instructions rather than provider-specific code, so GPT, Claude, Gemini, Grok, and local models can all load this skill when a request matches it.

How many AI models can I use with Inertia Rails Typescript?

As many as you like. As long as a model supports skills, you can use Inertia Rails Typescript with it — GPT, Claude, Gemini, Grok, DeepSeek, Mistral, Llama and more — all on TypingMind with your own API keys.

Is the Inertia Rails Typescript AI skill free?

Yes. It is published on GitHub by inertia-rails under the MIT license. You only pay your own AI provider for the tokens you use.

What are AI skills?

An AI skill is a reusable instruction bundle that teaches an AI model how to do one specific task. It follows the open Agent Skills format: a SKILL.md file with a name and description, plus any scripts, templates or reference files the model may need. The model reads the instructions only when your request matches the skill, so an installed skill costs nothing until it is used.

How are AI skills different from plugins or MCP servers?

A plugin or MCP server gives a model new tools to call — code that runs somewhere and returns a result. An AI skill gives the model knowledge and process instead: how to approach a task, which steps to follow, what good output looks like. Skills are plain Markdown, so they need no server, no API key and no runtime, and they work with any model.

View all

Set up your own AI workspace now

Get notified about new features and future giveaways by subscribing to our newsletter 👇