csr tangled client in solid-js forked from ptr.pet/untangled
untangled-fork AGENTS.md
15 kB · 262 lines
Markdown
at main

Agent Notes #

Build #

Use this as the main verification command:

rtk npm run build

This is a Solid/Vite TypeScript frontend. The build runs tsc -b && vite build. Do not start the Vite dev server from agent sessions; use the build command for verification.

Architecture Map #

Do not start by reading every file. Start from the area you are changing.

  • src/App.tsx: provider wiring only. Keep this small. It should compose app-wide providers and render AppRoutes.
  • src/routes.tsx: the declarative route table. Repo routes are nested under /:owner/:repo and use RepoLayout.
  • src/layout.tsx: global shell and topbar. Preserve the .untangled-shell wrapper so app pages keep the intended width and padding. There is intentionally no footer.
  • src/pages/home.tsx: home page and repository jump/recent/own-repo UI.
  • src/pages/oauth-callback.tsx: OAuth callback completion page.
  • src/pages/not-found.tsx: not-found page.
  • src/pages/search.tsx: global search page.
  • src/pages/repo.tsx: barrel exports for repo routes only.
  • src/pages/repo/shared.tsx: repo layout/context, shared repo frame/header/tabs, repo query keys, and useRepoQuery.
  • src/pages/repo/code.tsx: repo overview/tree page and blob/file viewer.
  • src/pages/repo/code-helpers.ts: pure code-route helpers such as ref/path resolution, language normalization, delayed loading, and navigation click checks.
  • src/pages/repo/issues.tsx: issue list, new issue, and issue detail.
  • src/pages/repo/issues-helpers.ts: issue-specific pure helpers such as comment thread building.
  • src/pages/repo/pulls.tsx: pull list, new pull, pull detail, and patch/diff rendering calls.
  • src/pages/repo/pulls-helpers.ts: pull-specific pure helpers such as state filter parsing.
  • src/components/common.tsx: generic UI primitives such as Avatar, LoadingState, StateBadge, and form/button/card style helpers.
  • src/components/repo.tsx: repo presentation components such as tabs, file rows, README/comment cards, branch pills, and repo skeletons.
  • src/components/code-view.tsx: code and diff presentation components, highlighting helper functions, CodeView, DiffView, and PullDiffView.
  • src/lib/api.ts: compatibility facade that re-exports domain APIs. Do not add implementation here.
  • src/lib/api/constants.ts: public service URLs and OAuth scope exports.
  • src/lib/api/appview.ts: appview JSON transport, fallback, and appview response types.
  • src/lib/api/backlinks.ts: Constellation backlink traversal and backlink pagination helpers.
  • src/lib/api/client.ts: shared ATProto RPC client creation and service URL normalization.
  • src/lib/api/hydration.ts: record hydration from appview/PDS records into resolved authors.
  • src/lib/api/identity.ts: auth RPC, identity resolver, actor resolution, avatar resolution.
  • src/lib/api/repos.ts: repo records, repo metadata, tree/blob/branch/tag/log/language APIs, compare APIs, and related response types.
  • src/lib/api/issues.ts: issue list/detail/create/comment/state APIs and issue types.
  • src/lib/api/pulls.ts: pull list/detail/create/comment/status/patch APIs and pull types.
  • src/lib/api/stars.ts: repo star summary/count/create/delete APIs and star types.
  • src/lib/api/records.ts: shared record utilities such as AT URI parsing and blob CID extraction.
  • src/lib/auth.tsx: auth provider and OAuth session state.
  • src/lib/live-events.tsx: live websocket event provider/hook.
  • src/lib/repo-utils.ts: repo URL/path helpers, file type checks, formatting, recent repo storage, language colors, tree sorting, and shared pure repo helpers.
  • src/index.css: global CSS plus explicit utility classes used to replace missing Tailwind arbitrary classes.

Repo Route Pattern #

Repo pages live under RepoLayout in src/pages/repo/shared.tsx.

  • RepoLayout creates the shared repo query once for the /:owner/:repo route subtree.
  • Child routes must call useRepoQuery() instead of creating their own repo query.
  • RepoFrame owns the shared repo chrome, tab links, star control, recent-repo storage, and live event subscription.
  • New repo-route behavior should usually go in a focused src/pages/repo/*.tsx file or a small helper beside it, not in src/App.tsx or src/routes.tsx.
  • Keep route files from growing indefinitely. Move pure helpers into *-helpers.ts files and reusable display pieces into src/components/repo.tsx.

API Module Pattern #

Use domain imports for new code:

import { getRepoTree } from '../../lib/api/repos';
import { createIssue } from '../../lib/api/issues';

The facade src/lib/api.ts remains for compatibility with existing imports, but new implementation should go into the relevant domain module. Shared internals should stay in a narrowly scoped helper such as src/lib/api/appview.ts, src/lib/api/backlinks.ts, src/lib/api/client.ts, src/lib/api/hydration.ts, src/lib/api/records.ts, or src/lib/api/stateful.ts.

Guidelines:

  • Do not add new implementation to src/lib/api.ts.
  • Prefer keeping public types next to the domain module that exposes the API.
  • Keep ATProto/PDS resolution rules centralized; repo UI record hydration should resolve the actor/PDS first and call the record endpoint against that PDS.
  • Do not use public.api.bsky.app for repo listRecords or record hydration.

Styling Source Of Truth #

This frontend is intended to match the upstream Tangled app templates in:

../tangled-upstream/appview/pages

Useful upstream files:

  • templates/layouts/base.html
  • templates/layouts/repobase.html
  • templates/repo/index.html
  • templates/repo/blob.html
  • templates/repo/issues/issues.html
  • templates/repo/issues/fragments/issueListing.html
  • templates/repo/pulls/pulls.html
  • templates/repo/pulls/fragments/*
  • static/tw.css

When matching visuals, compare against those templates before inventing new layout/styling.

Upstream Comparison Workflow #

For Tangled parity work, use upstream as the contract and compare details before changing local components:

  • Start from the matching upstream template in ../tangled-upstream/appview/pages/templates/..., then check nearby Go/router files when behavior or icon names are data-driven.
  • For repo chrome, templates/layouts/repobase.html is the main reference. Confirm header grouping, action buttons, tab icons, label spacing, font sizes, and vertical padding against that file before patching src/pages/repo/shared.tsx.
  • For code/blob views, compare templates/repo/index.html and templates/repo/blob.html before changing src/pages/repo/code.tsx, src/components/code-view.tsx, or file-view CSS.
  • Treat screenshots as prompts to inspect upstream source, not as the only source of truth.
  • Small differences such as gap-*, py-*, icon choice, and short-rev styling matter.
  • Remove or hide upstream controls that are not implemented locally instead of shipping fake UI.
  • External upstream-only affordances can link to https://tangled.org, such as repo stars and /:owner/:repo/feed.atom.

Local UI Style #

Upstream Tangled templates are the baseline, but Untangled should also preserve the local design language already present in the Solid app. Before copying an upstream class literally, compare nearby local pages and shared components.

  • Favor a quiet, dense tool UI: compact spacing, small radii, restrained borders, and flat page sections. Avoid marketing-style cards, oversized type, decorative gradients, and unnecessary nested panels.
  • When extending an existing multi-section page, copy its spacing rhythm before inventing a new one. Match the surrounding stack gaps, heading margins, description spacing, and form row density so sibling sections feel authored together rather than assembled from separate patterns.
  • Top-level route titles are usually plain lowercase labels. Use uppercase tracking only for compact metadata labels, table/list section labels, or places where the local surrounding UI already uses that treatment.
  • Action labels, nav labels, badges, pagination, and small utility links are generally lowercase. Keep this consistent unless the surrounding local component clearly uses title case.
  • Prefer established primitives (btn, btn-create, btn-flat, buttonStyles, StateBadge, ToggleButton) over custom button and badge stacks. Preserve their icon sizes, min-heights, padding, hover behavior, and inner icon/text grouping.
  • Icon buttons and icon+text actions should use Lucide icons already used in the app. Keep icons visible, aligned, and sized consistently with adjacent controls.
  • Badges shown next to controls should match the controls' visual density and height. Avoid badge styles that look like separate one-off pills unless a shared badge component already does that.
  • For repeated control rows such as checkboxes, toggles, or small preferences, reuse the same DOM structure and utility classes as nearby controls instead of building a visually similar variant. Small markup differences often create visible spacing drift even when the text and colors match.
  • Prefer lightweight interaction patterns for local preferences: save immediately when the change is unambiguous, keep temporary drafts only where validation requires it, and avoid extra cards or explicit save actions unless the setting genuinely needs batching or confirmation.
  • Dialogs and destructive/creation popovers should feel like app chrome, not a page section: center modal dialogs in the viewport, use a real backdrop when blocking interaction, and prefer spacing over extra separator lines when the header/body relationship is already clear.
  • When Tailwind utilities are missing from public/static/tw.css, add a small explicit .untangled-* rule in src/index.css rather than relying on an unavailable arbitrary class.

Tailwind/CSS Pitfall #

The checked-in public/static/tw.css does not include all arbitrary Tailwind classes. Avoid relying on classes such as:

  • grid-cols-[...]
  • [overflow-wrap:anywhere]
  • dark:[&_code]:...
  • arbitrary safe-area or min-height utilities

If a class is not present in public/static/tw.css, add an explicit .untangled-* rule in src/index.css instead.

Repo UI Notes #

  • Preserve the .untangled-shell wrapper in RootShell; widening pages changes the app layout.
  • Do not add a footer unless explicitly requested.
  • File/tree ordering should be folders first, then files alphabetically. This is implemented in sortedTreeEntries in src/lib/repo-utils.ts.
  • File/blob rendering uses CodeView in src/components/code-view.tsx.
  • PR diffs use DiffView, which parses unified patches into collapsible per-file panels and reuses CodeView.
  • Repo overview and blob pages should resolve HEAD to the default branch for user-facing links when possible.
  • Keep unimplemented upstream features visually inert rather than adding fake behavior.
  • Repo commit lists should show author avatars like upstream. Upstream maps verified commit author emails to DIDs server-side; the local app can render Avatar when the commit author email is already a DID, otherwise use PlaceholderAvatar.
  • The upstream placeholder avatar is a rounded gray background with a centered user-round icon. Use PlaceholderAvatar from src/components/common.tsx instead of a plain empty circle.
  • Do not show a verified-looking commit badge unless signature validity is actually checked. Use the neutral commit badge/icon for commit hashes.
  • Repo stars must count backlinks for both sh.tangled.feed.star:subject.did and legacy/alternate sh.tangled.feed.star:subjectDid, then dedupe hydrated refs.
  • Star and unstar should be optimistic. Unstar deletes the current user's sh.tangled.feed.star record and should update local state without refetching.
  • While star summary is loading, make the star control unclickable and show the upstream-style loader-circle spinner (LoaderCircle with animate-spin locally).
  • Markdown rendering should not enable hard line breaks globally for README-style content; marked should use breaks: false.

Editing Guidance #

  • Keep src/App.tsx small.
  • Keep route declarations in src/routes.tsx.
  • Keep global shell/topbar work in src/layout.tsx.
  • Keep top-level non-repo pages in src/pages.
  • Keep repo-route behavior in src/pages/repo/*.tsx.
  • Keep repo-route pure helpers in nearby src/pages/repo/*-helpers.ts files.
  • Keep generic display components in src/components/common.tsx.
  • Keep repo-specific display components in src/components/repo.tsx and src/components/code-view.tsx.
  • Keep shared pure repo helpers in src/lib/repo-utils.ts.
  • Do not add large page logic back into src/App.tsx.
  • Do not remove existing behavior while restructuring.
  • Run rtk npm run build after meaningful changes.

Current Size Guide #

Approximate current file roles:

  • src/App.tsx: tiny provider shell.
  • src/layout.tsx: global topbar/shell.
  • src/routes.tsx: route table.
  • src/pages/repo/code.tsx: largest repo route; split further if code/blob logic grows.
  • src/pages/repo/pulls.tsx: pull routes and patch/diff UI.
  • src/pages/repo/issues.tsx: issue routes.
  • src/lib/api/*: domain modules own their public implementations; shared plumbing is split across focused helper modules.

RTK (Rust Token Killer) - Token-Optimized Commands #

When running shell commands, always prefix with rtk. This reduces context usage by 60-90% with zero behavior change. If rtk has no filter for a command, it passes through unchanged — so it is always safe to use.

Key Commands #

# Git (59-80% savings)
rtk git status          rtk git diff            rtk git log

# Files & Search (60-75% savings)
rtk ls <path>           rtk read <file>         rtk grep <pattern>
rtk find <pattern>      rtk diff <file>

# Test (90-99% savings) — shows failures only
rtk pytest tests/       rtk cargo test          rtk test <cmd>

# Build & Lint (80-90% savings) — shows errors only
rtk tsc                 rtk lint                rtk cargo build
rtk prettier --check    rtk mypy                rtk ruff check

# Analysis (70-90% savings)
rtk err <cmd>           rtk log <file>          rtk json <file>
rtk summary <cmd>       rtk deps                rtk env

# GitHub (26-87% savings)
rtk gh pr view <n>      rtk gh run list         rtk gh issue list

# Infrastructure (85% savings)
rtk docker ps           rtk kubectl get         rtk docker logs <c>

# Package managers (70-90% savings)
rtk pip list            rtk pnpm install        rtk npm run <script>

Rules #

  • In command chains, prefix each segment: rtk git add . && rtk git commit -m "msg"
  • For debugging, use raw command without rtk prefix
  • rtk proxy <cmd> runs command without filtering but tracks usage