Glycemicgpt UI Foundation
lumose-health/GlycemicGPT
A skill your agent uses when adding or changing GlycemicGPT web UI structure, shared styling, Tailwind classes, semantic theme tokens, typography, base primitives, product UI components, TextInput…
apps/web UI — routes, @repo/ui, TanStack Start server functions and collections, navigation (Link vs useNavigate), forms (useForm + createFormSubmitHandler + fieldErrorsAsStrings for Zod field…
$ npx skills add latitude-dev/latitude-llm --skill web-frontend -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install latitude-dev/latitude-llm web-frontend --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/latitude-dev/latitude-llm.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.agents/skills/web-frontend .claude/skills/web-frontend && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "web-frontend" agent skill from https://github.com/latitude-dev/latitude-llm/tree/development/.agents/skills/web-frontend into .claude/skills/web-frontend/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "web-frontend", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/latitude-dev/latitude-llm/tree/development/.agents/skills/web-frontendType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add latitude-dev/latitude-llm --skill web-frontend -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install latitude-dev/latitude-llm web-frontend --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/latitude-dev/latitude-llm.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.agents/skills/web-frontend .agents/skills/web-frontend && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "web-frontend" agent skill from https://github.com/latitude-dev/latitude-llm/tree/development/.agents/skills/web-frontend into .agents/skills/web-frontend/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "web-frontend", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add latitude-dev/latitude-llm --skill web-frontend -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install latitude-dev/latitude-llm web-frontend --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/latitude-dev/latitude-llm.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.agents/skills/web-frontend .cursor/skills/web-frontend && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "web-frontend" agent skill from https://github.com/latitude-dev/latitude-llm/tree/development/.agents/skills/web-frontend into .cursor/skills/web-frontend/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "web-frontend", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/latitude-dev/latitude-llm.git --path .agents/skills/web-frontend--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add latitude-dev/latitude-llm --skill web-frontend -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install latitude-dev/latitude-llm web-frontend --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/latitude-dev/latitude-llm.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.agents/skills/web-frontend .gemini/skills/web-frontend && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "web-frontend" agent skill from https://github.com/latitude-dev/latitude-llm/tree/development/.agents/skills/web-frontend into .gemini/skills/web-frontend/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "web-frontend", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install latitude-dev/latitude-llm web-frontendInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add latitude-dev/latitude-llm --skill web-frontend -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/latitude-dev/latitude-llm.git skills-src && mkdir -p .github/skills && cp -r skills-src/.agents/skills/web-frontend .github/skills/web-frontend && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "web-frontend" agent skill from https://github.com/latitude-dev/latitude-llm/tree/development/.agents/skills/web-frontend into .github/skills/web-frontend/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "web-frontend", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add latitude-dev/latitude-llm --skill web-frontend -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install latitude-dev/latitude-llm web-frontend --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/latitude-dev/latitude-llm.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.agents/skills/web-frontend .opencode/skills/web-frontend && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "web-frontend" agent skill from https://github.com/latitude-dev/latitude-llm/tree/development/.agents/skills/web-frontend into .opencode/skills/web-frontend/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "web-frontend", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
web-frontendapps/web UI — routes, @repo/ui, TanStack Start server functions and collections, navigation (Link vs useNavigate), forms (useForm + createFormSubmitHandler + fieldErrorsAsStrings for Zod field…
Web Frontend is an agent skill from latitude-dev/latitude-llm. apps/web UI — routes, @repo/ui, TanStack Start server functions and collections, navigation (Link vs useNavigate), forms (useForm + createFormSubmitHandler + fieldErrorsAsStrings for Zod field errors), Tailwind layout rules, design-system updates, and useEffect / useMountEffect policy.
Its SKILL.md is about 5.2k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Frontend & Design, covering Design systems, Frontend development and CSS and styling. It works with TanStack, Tailwind CSS and Zod. The repository describes itself as: Open-source observability for AI agents. Find where your agents fail, dispatch your coding agent to fix it, and verify the fix against real traces. The licence is MIT.
Read from SKILL.md and the folder at commit 87e8aa0. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
No scripts in the folder and no shell commands in SKILL.md (its code samples are typescript).
From the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Web Frontend loads about 5.2k tokens when it runs. Until then it costs about 75 tokens; SKILL.md has 1,903 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from latitude-dev/latitude-llm at commit 87e8aa0, republished under its MIT licence (© latitude-dev). 1,903 words, ~5,222 tokens.
.claude/skills/web-frontend/SKILL.md (or your agent's skills folder).apps/web)When to use: apps/web UI — routes, @repo/ui, TanStack Start server functions and collections, navigation (Link vs useNavigate), forms (useForm with createFormSubmitHandler + fieldErrorsAsStrings when Zod validation errors should appear on fields), Tailwind layout rules, design-system updates, and useEffect / useMountEffect policy.
Before designing or editing any user-facing UI, read the root design.md. It defines the Latitude product UI rules for reuse-first discovery, composition, hierarchy, spacing, actions, responsive behavior, and route versus modal versus drawer decisions.
Treat packages/ui/src/components/, packages/ui/src/tokens/, the live apps/design-system inventory, and adjacent apps/web routes as the implementation source of truth. Search for an existing component and a comparable in-product pattern before creating a component, introducing custom styling, or adding a new token. Follow design.md when deciding whether new UI is justified; follow this skill for the required React, TanStack, route, form, and component APIs.
For project-route UI, use the local -components/section-header.tsx SectionHeader once for the route-level header, matching the Behaviors page's Layout.Header composition. A project overview defaults to the standard variant so its title has the same size and weight as the Behaviors route header; use variant="xl" only when the task and a comparable existing route justify it. Import the existing header and layout rather than recreating their structure or classes locally.
Project overview content has a strict default hierarchy: metric values may use Text.H5; panels use muted Text.H6 labels; repeated row and issue titles use compact Text.H6B; supporting copy uses muted Text.H6. Do not use Text.H3*, Text.H4*, or Text.H5* as panel, row, issue, or block titles. Do not use SectionHeader as a panel heading.
For project overview metrics, first inspect the compact AggregationItem strips in users/-components/users-analytics-panel.tsx, tools/-components/tools-analytics-panel.tsx, and -components/aggregations/general-aggregations.tsx. Preserve that anatomy and keep metrics in one horizontally scrollable row; do not create a grid, separate Card per metric, or a route-local approximation of the existing aggregation item. Detail sections use muted labels plus divide-y rows, not nested cards or dashboard-specific mini-panels. Read the Project Overview Contract in design.md before implementation.
apps/web/src/routes/ and packages/ui/src/components/.apps/design-system as the visual and behavioral reference. Do not use V1 as a default source of UI guidance.The project uses React 19. Follow modern patterns and avoid deprecated APIs:
forwardRef — ref is a regular prop in React 19. Declare it in the props type and destructure it directly.ElementRef — use React.ComponentRef<typeof SomeComponent> instead (the ElementRef alias is deprecated).useMemo / useCallback / React.memo — the React Compiler (enabled in the build) auto-memoizes. Only add manual memoization when profiling shows a concrete bottleneck; remove existing wrappers when they have no measured benefit.use() for consuming promises and context where appropriate.// ❌ Deprecated React 18 pattern
const Input = forwardRef<ElementRef<typeof Primitive>, InputProps>(({ className, ...props }, ref) => (
<Primitive ref={ref} {...props} />
))
Input.displayName = "Input"
// ✅ React 19 — ref is a regular prop
function Input({ className, ref, ...props }: InputProps & { ref?: React.Ref<React.ComponentRef<typeof Primitive>> }) {
return <Primitive ref={ref} {...props} />
}Text from @repo/ui for text contentButton from @repo/ui for buttonsText inside Button. Button already sets font size, weight, and color; use plain text (and optional icons) as direct children. Wrapping the label in Text duplicates styles (e.g. avoid <Button><Text.H5>Save</Text.H5></Button>).lucide-react and pass the component to @repo/ui’s Icon via the icon prop (e.g. <Icon icon={Pencil} size="sm" />). Prefer that over raw <Pencil /> so shared sizing and color tokens apply. Buttons and other primitives that accept an icon prop follow the same pattern; otherwise wrap with Icon.GoogleIcon and GitHubIcon from @repo/ui for OAuth provider iconsDefault to the short form — <Modal title=… description=… footer=… open dismissible onOpenChange={…}>{children}</Modal>. It auto-wraps children in Modal.Body with the standard px-6 padding and the same scroll behavior every other modal uses, so content inside it can't drift out of the design system. This is the shape RenameProjectModal (the form reference cited above) uses — treat it as the canonical pattern.
<Modal
open
dismissible
onOpenChange={(next) => (!next ? onClose() : undefined)}
title="Change sampling rate"
description="Percentage of incoming traces this evaluation runs against."
footer={
<>
<CloseTrigger />
<Button onClick={() => void form.handleSubmit()}>Save</Button>
</>
}
>
<form onSubmit={…}>{/* fields */}</form>
</Modal>Reach for the composition form (Modal.Root / Modal.Content / Modal.Header / Modal.Body / Modal.Footer) only when the short form can't express what you need:
title + description — render <Modal.Header>{custom JSX}</Modal.Header> directly.undefined.Notes:
dismissible defaults to false — pass it to show the close X.scrollable defaults to true. For short bodies that shouldn't grow to fill height, pass scrollable={false}.<Modal.Body> while using the short form — children are already wrapped, double-wrapping nests padding.Place React components close to the routes that use them, inside a -components/ subfolder within the route directory. This keeps route files (which TanStack Router auto-discovers) clearly separated from supporting components.
routes/_authenticated/projects/$projectId/datasets/
├── index.tsx # route file
├── $datasetId.tsx # route file
└── -components/ # supporting components for these routes
├── dataset-table.tsx
├── row-detail-panel.tsx
└── version-badge.tsx-components/ folderdomains/ directories (apps/web/src/domains/) are for state management only: server functions (writes) and collections/queries (reads) — not UI componentspackages/ui (or replacing a placeholder export with a real implementation), update apps/web/src/routes/design-system.tsx to include a usage example for that component in both light and dark mode previews.apps/web/src/routes/design-system.tsx as the canonical visual inventory for @repo/ui components.The web app uses a server-centric, query-driven architecture built on the TanStack ecosystem. No Zustand, Redux, or global stores.
Server functions — All data fetching and mutations use createServerFn from @tanstack/react-start:
import { Effect } from "effect"
import { ProjectRepository, createProjectUseCase } from "@domain/projects"
import { ProjectRepositoryLive, SqlClientLive } from "@platform/db-postgres"
import { getPostgresClient } from "../../server/clients.ts"
// Query (GET)
export const listProjects = createServerFn({ method: "GET" }).handler(async () => {
const { organizationId } = await requireSession()
const client = getPostgresClient()
return await Effect.runPromise(
Effect.gen(function* () {
const repo = yield* ProjectRepository
return yield* repo.findAll()
}).pipe(
Effect.provide(ProjectRepositoryLive),
Effect.provide(SqlClientLive(client, organizationId)),
),
)
})
// Mutation (POST) with Zod validation
export const createProject = createServerFn({ method: "POST" })
.inputValidator(createProjectSchema)
.handler(async ({ data }) => {
const { userId, organizationId } = await requireSession()
const client = getPostgresClient()
return await Effect.runPromise(
createProjectUseCase({...}).pipe(
Effect.provide(ProjectRepositoryLive),
Effect.provide(SqlClientLive(client, organizationId)),
),
)
})Server functions live in apps/web/src/domains/*/functions.ts.
Collections — Client-side reactive state uses TanStack React DB + Query via queryCollectionOptions:
const projectsCollection = createCollection(
queryCollectionOptions({
queryClient,
queryKey: ["projects"],
queryFn: () => listProjects(),
getKey: (item) => item.id,
onInsert: async ({ transaction }) => { /* optimistic insert */ },
onUpdate: async ({ transaction }) => { /* optimistic update */ },
onDelete: async ({ transaction }) => { /* optimistic delete */ },
}),
)
export const useProjectsCollection = (...) => useLiveQuery(...)Collection files live in apps/web/src/domains/*/collection.ts.
Route middleware vs route data
beforeLoad for middleware-style checks that should block the route tree early: auth redirects, authorization gates, and other preconditions.loader for data the route or layout actually renders. This keeps rendered data in TanStack Router's loader lifecycle, so it can use staleTime, useLoaderData({ select }), and avoid unnecessary refetching on same-route search-param navigations.loader once instead of duplicating it across beforeLoad and loader.getRouteApi("...") instead of repeating the route id string in every file.export const Route = createFileRoute("/admin")({
beforeLoad: async () => {
const session = await getSession()
if (!session?.user.isAdmin) throw redirect({ to: "/" })
},
})export const Route = createFileRoute("/_authenticated")({
staleTime: Infinity,
loader: async () => {
const session = await getSession()
if (!session) throw redirect({ to: "/login" })
const sessionData = session.session as Record<string, unknown>
const organizationId =
typeof sessionData.activeOrganizationId === "string" ? sessionData.activeOrganizationId : null
if (!organizationId) throw redirect({ to: "/welcome" })
return {
user: session.user,
organizationId,
}
},
})const authenticatedRoute = getRouteApi("/_authenticated")
export function useAuthenticatedUser() {
return authenticatedRoute.useLoaderData({ select: (data) => data.user })
}Key rules:
useState for local UI state (modals, form visibility); no global storesgetQueryClient().invalidateQueries({ queryKey: [...] })useForm + form.Field)<Link> vs useNavigateRule: if navigation is triggered by a user clicking something, render a <Link> (from @tanstack/react-router). Reserve useNavigate for programmatic redirects — work the user didn't directly click "go there" for.
A real anchor (<Link> → <a href>) is the only way to get:
href (hover-preview the URL, right-click → copy/open, browser history correctness)onKeyDown| Trigger | Use |
|---|---|
| User clicks a button / badge / row / link-styled element to go to a different page | <Link> |
| Same-route navigation that only flips a search param (drawer toggle, "apply saved search" on the page you're already on) | useNavigate is fine — there is no new document to link to |
After a mutation completes (createX → go to the new resource, deleteX → go back to the listing) | useNavigate |
| Auth flows (sign in, sign out, OAuth callback, redirect-after-login) | useNavigate |
Do not put role="button", onClick, and a hand-rolled onKeyDown on a Badge/div/span to call navigate(...). That re-implements (badly) what <Link> already provides, and silently breaks cmd-click / middle-click / right-click flows.
// ❌ Bad — click-to-navigate via useNavigate
const navigate = useNavigate()
function open() {
navigate({ to: "/projects/$projectSlug/settings/flaggers", params: { projectSlug }, search: { flagger: slug } })
}
return (
<Badge
role="button"
tabIndex={0}
onClick={open}
onKeyDown={(e) => (e.key === "Enter" || e.key === " ") && open()}
>
{label}
</Badge>
)
// ✅ Good — real anchor wraps the visual badge
return (
<Link
to="/projects/$projectSlug/settings/flaggers"
params={{ projectSlug }}
search={{ flagger: slug }}
aria-label={`Open the ${name} flagger settings`}
className="inline-flex"
>
<Badge variant="secondary" size="small" className="cursor-pointer hover:bg-muted">
{label}
</Badge>
</Link>
)Badge (and other @repo/ui primitives that are plain <div>s without asChild) should be wrapped inside the <Link> as visual children — the <Link> is the interactive anchor.
For <Button> (which does support asChild), use the Radix Slot pattern: <Button asChild><Link to="…">…</Link></Button>.
When the clickable element sits inside a larger row-level click handler, add data-no-navigate to the <Link> (the parent handler skips elements under [data-no-navigate]) and onClick={(e) => e.stopPropagation()} for belt-and-suspenders.
If clicking an InfiniteTable row opens a different page, use the renderRowLink prop — not onRowClick + useNavigate. renderRowLink is router-agnostic: the table renders a stretched-link overlay, the app supplies the <Link> element.
<InfiniteTable
data={items}
columns={columns}
getRowKey={(r) => r.id}
renderRowLink={(row, props) => (
<Link to="/items/$id" params={{ id: row.id }} aria-label={`Open ${row.name}`} {...props} />
)}
/>Keep onRowClick only for same-route row interactions: selecting a row to open a drawer, applying a saved filter on the same page, toggling expansion state, etc. — the cases where there is no new URL to navigate to.
The global command palette (apps/web/src/components/command-palette/, mounted in
_authenticated.tsx) is the keyboard launcher for navigation, actions, contextual entity
actions, and in-project search. Full design + maintenance guide: dev-docs/command-palette.md — read it before changing palette behavior.
Keep it in sync when you add UI. Anything navigable or actionable should also be reachable from the palette:
apps/web/src/domains/projects/project-sections.ts. The sidebar, settings sub-nav, and the palette navigation all consume that module, so it surfaces everywhere automatically — don't hardcode a nav entry in the palette.command-palette/commands/use-global-commands.tsx (switch/navigate actions rank above create actions; keep Log out last).useRegisterCommands(...) (section: "context", a group label, reusing the view's existing handler).commands/use-*-search-commands hook gated on useCurrentProject() + a non-empty query, then wire a group into command-palette.tsx.The palette runs cmdk with shouldFilter={false} and filters in React — never rely on cmdk's built-in keywords/filter for query-driven rows (cmdk snapshots keywords on first registration). See the dev-doc for the rationale.
createFormSubmitHandler + fieldErrorsAsStrings)When: useForm submits work that can fail with Zod validation (for example server functions using inputValidator), and you want inline errors on @repo/ui fields (not only a toast).
Module: apps/web/src/lib/form-server-action.ts
| Helper | Use |
|---|---|
createFormSubmitHandler | Pass as useForm({ onSubmit: createFormSubmitHandler(async (value) => { ... }, { onSuccess, onError }) }). On validation failure it maps serialized Zod issues onto TanStack Form field meta via extractFieldErrors in apps/web/src/lib/errors.ts. Non-field errors go to onError. On success it resets the form and runs onSuccess. |
fieldErrorsAsStrings | On every Input, Textarea, or other control with an errors prop inside form.Field, set errors={fieldErrorsAsStrings(field.state.meta.errors)} so those meta errors display. |
Always use both when you want Zod-driven field errors: the submit handler wires errors into form state; the helper wires form state into @repo/ui.
Do not duplicate the inline pattern field.state.meta.errors.length > 0 ? field.state.meta.errors.map(String) : undefined — use fieldErrorsAsStrings instead.
Reference: apps/web/src/routes/_authenticated/index.tsx — RenameProjectModal: createFormSubmitHandler in useForm (~line 225), fieldErrorsAsStrings on the name field Input (~line 287).
flex, flex-col, flex-row)m-*, mx-*, my-*, mt-*, etc.)gap utilities for spacing between elements (gap-*, gap-x-*, gap-y-*)p-* (padding) for internal spacing within containerscn)With cn(), use object syntax { "class-name": condition } — not short-circuit condition && "class-name".
// ❌ Bad
<div className={cn("base-class", isActive && "bg-accent")} />
// ✅ Good
<div className={cn("base-class", { "bg-accent": isActive })} />// ❌ Bad - using margins and space-y
<div className="space-y-4 mt-4">
<div className="mb-2">Item 1</div>
<div className="mb-2">Item 2</div>
</div>
// ✅ Good - using flexbox with gap
<div className="flex flex-col gap-4 pt-4">
<div>Item 1</div>
<div>Item 2</div>
</div>useEffect policy)useEffect directly in components; use useMountEffect from @repo/ui for mount/unmount-only sync (listeners, imperative widgets, one-time setup).useEffect is unavoidable, add TODO(frontend-use-effect-policy) with a short reason.Prefer: derive values during render; run work in event handlers; controlled vs uncontrolled via value !== undefined; reset by key when an entity id changes.
Avoid: deriving state from props in an effect; fetching in effects to set state; mirroring props into local state; effects as command dispatchers.
import { useMountEffect } from "@repo/ui"
useMountEffect(() => {
const cleanup = subscribeToExternalSystem()
return () => cleanup()
})© latitude-dev, MIT. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in .agents/skills/web-frontend of latitude-dev/latitude-llm.
Open the folder on GitHubat commit 87e8aa0
Web Frontend next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Web Frontend this skilllatitude-dev/latitude-llm | 4.7k | — | ~5.2k | Automated safety check: Pass | MIT | |
| Glycemicgpt UI Foundationlumose-health/GlycemicGPT | 141 | — | ~707 | Automated safety check: Pass | GPL-3.0 | |
| Design StyleCastor6/tactus | 376 | 1 repos | ~2.1k | Automated safety check: Pass | Apache-2.0 | |
| Frontend UI FunctionalvictorGPT/vibeusage | 131 | — | ~939 | Automated safety check: Pass | MIT | |
| Bryl Minimal Designbryllim/bryl-minimal-design | 114 | — | ~2.9k | Automated safety check: Pass | MIT | |
| Using Ouds Web Version Major MinorOrange-OpenSource/Orange-Boosted-Bootstrap | 222 | — | ~4.1k | Automated safety check: Pass | MIT |
lumose-health/GlycemicGPT
A skill your agent uses when adding or changing GlycemicGPT web UI structure, shared styling, Tailwind classes, semantic theme tokens, typography, base primitives, product UI components, TextInput…
Castor6/tactus
A skill your agent uses whenever the user asks to build, create, design, develop, improve, or style any frontend interface or visual element.
victorGPT/vibeusage
A skill your agent uses when building or refactoring functional React/Vite/Tailwind UI pages, templates, or component libraries that need consistent structure, tokenized styling, accessibility…
bryllim/bryl-minimal-design
Apply the bryl-minimal design language — a monochrome, typography-driven minimal aesthetic with halftone dot textures, pixel-font display headings, tiny uppercase monospace labels, soft large-radius…
Orange-OpenSource/Orange-Boosted-Bootstrap
Provides comprehensive knowledge of the OUDS Web library (Orange Unified Design System for Web), a Bootstrap-based CSS/JS framework for building Orange-branded web interfaces.
jiushiwon/wg-skills
A skill your agent uses when generating UI for a specific scenario (mobile/PC/官网/管理端/营销页/文档/金融/原生/3D), when refactoring an existing HTML/Vue/React project to a unified design system, when extracting…
latitude-dev/latitude-llm
Configure Better Auth server and client, set up database adapters, manage sessions, add plugins, and handle environment variables.
latitude-dev/latitude-llm
Create, validate, preview, and publish self-contained HTML artifacts.
latitude-dev/latitude-llm
Continuously monitor GitHub PR CI checks and automatically fix failures until all checks pass.
latitude-dev/latitude-llm
This skill should be used when the user asks to "create a Temporal workflow", "write a Temporal activity", "debug stuck workflow", "fix non-determinism error", "Temporal Python", "Temporal…
latitude-dev/latitude-llm
Review the current conversation context and git changes, then persist durable repository knowledge into dev-docs/.md by domain and into AGENTS.md for cross-cutting repo rules.
latitude-dev/latitude-llm
Enables or disables Latitude production maintenance mode by redirecting all publicly exposed production services to the Better Stack status page.
Works with
Categories
apps/web UI — routes, @repo/ui, TanStack Start server functions and collections, navigation (Link vs useNavigate), forms (useForm + createFormSubmitHandler + fieldErrorsAsStrings for Zod field…. Web Frontend is an agent skill from latitude-dev/latitude-llm. apps/web UI — routes, @repo/ui, TanStack Start server functions and collections, navigation (Link vs useNavigate), forms (useForm + createFormSubmitHandler + fieldErrorsAsStrings for Zod field errors), Tailwind layout rules, design-system updates, and useEffect / useMountEffect policy.
Web Frontend fits situations like: tasks that involve Design systems; tasks that involve Frontend development; tasks that involve CSS and styling.
Run `npx skills add latitude-dev/latitude-llm --skill web-frontend -a claude-code`. Or copy the skill folder (.agents/skills/web-frontend in latitude-dev/latitude-llm) into .claude/skills/web-frontend in your project. Claude Code loads it when a task matches its description.
Run `npx skills add latitude-dev/latitude-llm --skill web-frontend -a codex`. Or copy the skill folder (.agents/skills/web-frontend in latitude-dev/latitude-llm) into .agents/skills/web-frontend in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add latitude-dev/latitude-llm --skill web-frontend -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/web-frontend, .gemini/skills/web-frontend, .github/skills/web-frontend and .opencode/skills/web-frontend in your project.
SKILL.md names no scripts, command-line tools or credentials: Web Frontend is instructions for the agent only.
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Web Frontend is published under the MIT licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 5.2k tokens (SKILL.md is roughly 21k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Web Frontend: Glycemicgpt UI Foundation (lumose-health/GlycemicGPT, 141 stars), Design Style (Castor6/tactus, 376 stars), Frontend UI Functional (victorGPT/vibeusage, 131 stars) and Bryl Minimal Design (bryllim/bryl-minimal-design, 114 stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
latitude-dev (a GitHub organization) maintains it in latitude-dev/latitude-llm, which has 4,712 GitHub stars. The repository holds 28 skills in this directory. The repository was last updated on October 6, 2026.
Source: latitude-dev/latitude-llm on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.