{element.props.title}
- {element.props.description && ( -{element.props.description}
- )} -diff --git a/.agents/skills/remix/SKILL.md b/.agents/skills/remix/SKILL.md new file mode 100644 index 0000000..03fd659 --- /dev/null +++ b/.agents/skills/remix/SKILL.md @@ -0,0 +1,501 @@ +--- +name: remix +description: Build and review Remix 3 applications using the `remix` npm package and subpath imports. Use when working on Remix app structure, routes, controllers, middleware, validation, data access, auth, sessions, file uploads, server setup, UI components, hydration, navigation, or tests. +--- + +# Build a Remix App + +Use this skill for end-to-end Remix app work. It should help the agent choose the right layer +first, reach for the right package, and avoid the most common Remix-specific mistakes. + +## What Remix Is + +Remix 3 is a server-first web framework built on Web APIs such as `Request`, `Response`, `URL`, +and `FormData`. All packages ship from a single npm package, `remix`, and are imported via +subpath. There is no top-level `remix` import. + +A Remix app has four main pieces: + +- **Routes** in `app/routes.ts` define the typed URL contract and power `href()` generation. +- **Controllers and actions** implement that contract and return `Response` objects. +- **Middleware** composes request lifecycle behavior and populates typed context via + `context.set(Key, value)`. +- **Components** render UI with `remix/ui`. This is not React. A component receives a + `handle`, reads current props from `handle.props`, and returns a render function. + +## When To Use This Skill + +Use this skill for: + +- new features or refactors that touch routing, controllers, middleware, data, auth, sessions, UI, + or tests +- reviewing Remix app code for correctness, architecture, or framework usage +- answering "how should this be structured in Remix?" questions +- finding the right package, reference doc, or default pattern for a task + +## Load Only The References You Need + +Classify the task first, then load the smallest useful reference set. Each reference file starts +with a "What This Covers" section that lists the topics inside it — read that first to confirm +the file is relevant before reading the rest. + +Use the table below to find candidates. Loading more than two or three files at once is usually a +sign that the task hasn't been narrowed enough yet. + +| Task involves... | Start with | +| ----------------------------------------------------------------------------- | ------------------------------------------- | +| Defining URLs, writing controllers and actions, returning responses | `references/routing-and-controllers.md` | +| Composing the request lifecycle, ordering middleware, bridging to a server | `references/middleware-and-server.md` | +| Compiling and serving browser modules, asset URL namespaces, preloads | `references/assets-and-browser-modules.md` | +| Parsing input, validating with schemas, defining tables, querying, migrations | `references/data-and-validation.md` | +| Per-browser state, login flows, route protection, identity | `references/auth-and-sessions.md` | +| Component setup, state, lifecycle, updates, `queueTask`, context | `references/component-model.md` | +| Event handlers, styles, refs, click/key behavior, simple animations | `references/mixins-styling-events.md` | +| `clientEntry`, `run`, ``, navigation, `
` | `references/hydration-frames-navigation.md` | +| Router tests, component tests, test isolation | `references/testing-patterns.md` | +| Spring physics, tweens, layout transitions | `references/animate-elements.md` | +| Authoring custom reusable mixins | `references/create-mixins.md` | + +Common bundles: + +- **Form or CRUD feature** -> routing, data and validation, testing; add auth if user-specific +- **Protected area** -> auth and sessions, routing, testing +- **Interactive widget** -> component model, mixins and styling; add hydration only if it runs in + the browser +- **Browser asset pipeline** -> assets and browser modules, hydration, middleware and server +- **File upload** -> middleware and server, data and validation, testing +- **Navigation or frames** -> hydration, frames, navigation + +## Default Workflow + +1. **Classify the change.** Decide whether it changes the route contract, request lifecycle, data + model, auth or session behavior, or only UI. +2. **Start from the server contract.** Add or update `app/routes.ts` before wiring handlers or UI. +3. **Put code in the narrowest owner.** Favor route-local code first, then promote only when reuse + is real. +4. **Make the server path correct before adding browser behavior.** A route should return the right + `Response` via `router.fetch(...)` before you add `clientEntry(...)`, animations, or DOM + effects. +5. **Add middleware deliberately.** Keep fast-exit middleware early and request-enriching + middleware later. Export a typed `AppContext` from the root middleware stack and use it in + controllers. +6. **Validate input at the boundary.** Parse and validate `Request`, `FormData`, params, cookies, + and external payloads before they reach rendering or persistence logic. +7. **Hydrate only when necessary.** Prefer server-rendered UI. Use `clientEntry(...)` and `run(...)` + only for real browser interactivity or browser-only APIs. +8. **Test the narrowest meaningful layer.** Prefer router tests for route behavior. Use component + tests when the behavior is truly interactive or DOM-specific. +9. **Finish with verification.** Re-read the route flow, confirm auth and authorization boundaries, + and run the smallest relevant test and typecheck loop. + +## Project Layout + +Use these root directories consistently: + +- `app/` for runtime application code +- `db/` for migrations and local database files +- `public/` for static assets served as-is +- `test/` for shared helpers, fixtures, and integration coverage +- `tmp/` for uploads, caches, local session files, and other scratch data + +Inside `app/`, organize by responsibility: + +- `assets/` for client entrypoints and client-owned browser behavior +- `controllers/` for route-owned handlers and route-local UI +- `data/` for schema, queries, persistence setup, migrations, and runtime data initialization +- `middleware/` for request lifecycle concerns such as auth, sessions, uploads, and database + injection +- `ui/` for shared cross-route UI primitives +- `utils/` only for genuinely cross-layer helpers that do not clearly belong elsewhere +- `routes.ts` for the route contract +- `router.ts` for router setup and wiring + +### Placement Precedence + +When code could live in multiple places: + +1. Put it in the narrowest owner first. +2. If it belongs to one route, keep it with that route. +3. If it is shared UI across route areas, move it to `app/ui/`. +4. If it is request lifecycle setup, keep it in `app/middleware/`. +5. If it is schema, query, persistence, or startup data logic, keep it in `app/data/`. +6. Use `app/utils/` only as a last resort for truly cross-layer helpers. + +### Route Ownership + +- Use a flat file in `app/controllers/` for a simple leaf action, such as `app/controllers/home.tsx` +- Use a folder with `controller.tsx` when a route owns nested routes or multiple actions, such as + `app/controllers/account/controller.tsx` +- Mirror nested route structure on disk, such as `app/controllers/auth/login/controller.tsx` +- Keep route-local UI next to its owner, such as `app/controllers/contact/page.tsx` +- Move shared UI to `app/ui/` +- If a flat leaf grows child routes or multiple actions, promote it to a controller folder + +### Layout Anti-Patterns + +- Do not create `app/lib/` as a generic dumping ground +- Do not create `app/components/` as a second shared UI bucket when `app/ui/` already owns that + role +- Do not put shared cross-route UI in `app/controllers/` +- Do not put middleware or persistence helpers in `app/utils/` when they have a clearer home +- Do not create folders for simple leaf actions unless they are real controllers + +## Core Remix Rules + +- Import from `remix/- Sign in to your account to continue -
- - -{element.props.description}
- )} -{element.props.content}
, -}; -``` - -**Why this works**: The LLM _cannot_ deviate. It knows it has exactly three components. It knows what props they take. It has a strict recipe to follow. Limited choices, predictable results. - -**When to use json-render**: You have a set component library and want the AI to assemble UIs. You want progressive streaming. You need to validate output at runtime before it hits the user. - -**When to skip it**: You need total design freedom (custom landing pages). Your layout has deep nesting that's hard to represent flat. Your component library is constantly changing. - -The catalog is your design contract. Change it, regenerate the system prompt, done. - -## Which one should you use? - -These aren't competing tools. They're different layers of the same stack. - -- **Figma MCP**: Your design system is law. You need 1:1 match with Figma files. -- **agent-browser**: Speed and cost matter. The AI gets "semantic vision" to fix its own mistakes without burning context on screenshots. -- **json-render**: You need absolute consistency. Dashboards or internal tools where the AI assembles pre-approved building blocks. - -**Watch your context budget.** If the agent is iterating autonomously, every byte counts. - -- agent-browser (~1KB) beats Playwright screenshots (~50KB) -- json-render patches (~2KB) beat full code generation (~20KB) - -The more expensive your feedback, the fewer chances the AI gets to iterate. - -## The bottom line - -Same prompt, different outputs. That's how LLMs work. Constraints change the game. - -Design contracts (Figma MCP), feedback loops (agent-browser), and structured output (json-render) turn a chaotic generator into something predictable. - -These aren't silver bullets. Figma MCP has rate limits. agent-browser won't catch every pixel-perfect glitch. json-render isn't built for infinite design freedom. - -But guardrails work. When you constrain the problem space and make choices finite, you get code you can trust. - -Predictability through constraints. Not despite them. - ---- - -All code from this post is available at [ubmit/from-prompts-to-predictable-user-interfaces](https://github.com/ubmit/from-prompts-to-predictable-user-interfaces). Slides, demos, and full examples are all there. diff --git a/src/env.d.ts b/src/env.d.ts deleted file mode 100644 index aabef7f..0000000 --- a/src/env.d.ts +++ /dev/null @@ -1,2 +0,0 @@ -import "../.astro/types.d.ts"; -import "astro/client"; diff --git a/src/layouts/BaseLayout.astro b/src/layouts/BaseLayout.astro deleted file mode 100644 index 6a772fd..0000000 --- a/src/layouts/BaseLayout.astro +++ /dev/null @@ -1,39 +0,0 @@ ---- -import Header from "../components/Header.astro"; ---- - - -
- I'm Gui, a Frontend Engineer focused on crafting polished and user-first
- products. I work with AI agents to build software and explore new ways
- of engineering. You can read my ramblings on
- I'm diving deep into agentic engineering. I'm building software alongside AI coding agents and exploring how - to orchestrate multiple agents, manage context effectively, and - building predictable UIs from prompts. -
-
- On the same topic, I'm reading