Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
126 changes: 126 additions & 0 deletions .evolve/tangle-cloud-design-audit-2026-06-07.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,126 @@
# Product Design Audit

Status: implemented and verified locally
Product: Tangle Cloud blueprint catalog / registration / deploy flow
Primary users: deployers browsing service blueprints; operators registering capacity
Reference surfaces: existing Tangle Cloud chrome, Arena readability critique, `apps/tangle-cloud/PRODUCT_BRIEF.md`
Product brief: `apps/tangle-cloud/PRODUCT_BRIEF.md`

## Inventory
- Route/page: `/blueprints`, `/blueprints?view=grid`, `/blueprints?register=0`, `/blueprints/:id/deploy`
- Components: `BlueprintListing`, `ResultList`, `PageToolbar`, `StatusPill`, `BlueprintVisual`, `RegistrationDrawer`, `Header`, shared blueprint GraphQL hooks, shared wallet dropdown
- States: loading, cached/degraded, list, grid, mobile, disconnected register drawer, disconnected deploy gate
- Data dependencies: Envio indexer, direct chain fallback, selected Cloud network, wallet chain, React Query cache
- Known complaints: glass-on-glass catalog, duplicate page title, missing blueprint logo/image, button dots, no caching on revisit, localhost RPC failure after wallet connect, hidden wallet address, italic network text, hard-to-read colors/fonts, tiny status labels, AI Agent deploy/register blank screen

## Page Evaluations
### Blueprints Catalog
Purpose: choose a blueprint, compare capacity/trust, deploy or register.
Primary user decision: deploy available blueprint or register operator capacity.
Current score: 6/10 before; 8/10 after.
Target score: 9/10.
Findings:
- Page header duplicated the topbar breadcrumb and consumed vertical space without adding a decision.
- List rows used the same background family as the page and had no blueprint identity art.
- Mobile list forced desktop columns into 390px, hiding titles under action buttons.
- Grid cards hid actions until hover and could intermittently render blank under `content-visibility`.
Complaint ledger:
- Fixed: duplicate title removed; actions moved into toolbar.
- Fixed: list/card surfaces use elevated card background, stronger borders, and generated/default visuals.
- Fixed: mobile list has dedicated compact cards with identity, description, status, and actions.
- Fixed: deploy/register action links have explicit action classes and no pseudo-dot affordances.
- Fixed: status pills are larger and catalog capacity/audit pills omit decorative dots.
- Fixed: grid actions are visible without hover.
- Fixed: removed `content-visibility` from the result grid.
Alternatives:
- Keep dense desktop list only: 6/10; fails mobile and visual identity.
- Default to card wall everywhere: 7/10; better identity, worse operator comparison.
- Hybrid: desktop list/grid toggle with mobile-specific cards: 9/10; keeps density and mobile readability.
Decision: hybrid.
Changes shipped: `BlueprintListing`, `ResultList`, `PageToolbar`, `StatusPill`, `BlueprintVisual`, `styles.css`.
Verification: screenshots `desktop-blueprints-list.png`, `desktop-blueprints-grid-v3.png`, `mobile-blueprints-list-v3.png`; no page errors; no horizontal overflow.
Remaining risk: topbar breadcrumb still says `Blueprints`; acceptable after removing page title, but a future app-shell pass could move route context fully into page-local controls.

### Register Drawer
Purpose: register/preregister an active operator for selected blueprints.
Primary user decision: connect operator wallet or continue registration.
Current score: 7/10 before; 8/10 after.
Target score: 9/10.
Findings:
- `/blueprints?register=0` opened a nonblank drawer, but the drawer had two close controls.
Complaint ledger:
- Fixed: duplicate custom close button removed; Radix dialog close remains.
- Verified: mobile register screenshot shows connected-wallet gate, not a blank screen.
Alternatives:
- Keep drawer as-is: 6/10; looks broken.
- Replace with route page: 7/10; more work, less continuity from catalog.
- Keep drawer, remove duplicate close, preserve catalog context: 8/10.
Decision: keep drawer and remove duplicate control.
Verification: `mobile-blueprints-register-v3.png`; no page errors; no horizontal overflow.
Remaining risk: disconnected drawer still visually overlays a full-page screenshot while background content appears below in full-page captures; viewport behavior is correct.

### Deploy Gate
Purpose: prepare and submit a service request transaction.
Primary user decision: connect wallet, then configure instance.
Current score: 6/10 before; 8/10 after.
Target score: 9/10.
Findings:
- Disconnected deploy gate was generic, so a direct route such as `/blueprints/10/deploy` did not confirm the selected blueprint.
Complaint ledger:
- Fixed: disconnected deploy gate title includes the loaded blueprint name.
- Verified: `/blueprints/10/deploy` contains `AI Agent Sandbox` and `Connect`.
Alternatives:
- Generic connect gate: 6/10; route context lost.
- Full blueprint preview before wallet: 9/10; best UX but broader deploy-page composition.
- Contextual connect gate with blueprint name: 8/10; low-risk fix now.
Decision: contextual connect gate.
Verification: `desktop-ai-agent-deploy-v2.png`; no page errors; no horizontal overflow.
Remaining risk: richer disconnected preview belongs in a deeper deploy-flow pass.

## Cross-Cutting System Findings
- Navigation: removed catalog page header; topbar/sidebar remain the route shell.
- Theme: dark palette is less purple and less bright; card/list surfaces now separate from page background.
- Tables/charts: desktop list remains row-based; mobile list is not a squeezed table.
- Density: toolbar wraps on mobile instead of cramming into one 44px row.
- Copy/labels: no extra explanatory page title; statuses use larger text.
- Interactions: card actions always visible; register drawer no longer double-closes; deploy gate carries blueprint context.
- Responsiveness: 390px mobile has no horizontal overflow.
- Data truth: browse data follows selected Cloud network rather than connected wallet chain; connected wallet no longer forces read-only catalog to dead localhost RPC.
- Production/deploy: not deployed in this pass.

## Product Innovation Audit
- High-value innovation shipped: generated/default blueprint visual identity from deterministic category/name diagrams. This gives every blueprint a scannable artifact without trusting missing metadata images.
- Reliability innovation shipped: read-only blueprint queries use Cloud network selection, keep previous data, and retain cache for 30 minutes. Wallet chain is reserved for transaction context instead of browse context.
- Interaction innovation shipped: hybrid responsive catalog: desktop comparison list plus mobile action cards.
- Rejected: app-store hero/gallery treatment. It would improve screenshots but weaken operator comparison and contradict the infrastructure-console brief.
- Rejected: hiding register/deploy behind hover. It looks cleaner but makes primary actions feel missing and hurts touch devices.

## Verification
- Commands:
- `npx nx run tangle-cloud:typecheck`
- `npx nx build tangle-cloud`
- `npx nx test tangle-cloud` — 26 files, 167 tests passed
- `npx nx lint tangle-cloud` — passed with existing warnings
- `npx nx run ui-components:typecheck`
- `npx nx run tangle-shared-ui:test` — 5 suites, 74 tests passed
- `npx nx lint tangle-shared-ui` — passed with existing warnings
- `git diff --check`
- Browser checks:
- `/blueprints`
- `/blueprints?view=grid`
- `/blueprints?register=0`
- `/blueprints/0/deploy`
- `/blueprints/10/deploy`
- Screenshots:
- `.evolve/tangle-cloud-design-audit-2026-06-07/desktop-blueprints-list.png`
- `.evolve/tangle-cloud-design-audit-2026-06-07/desktop-blueprints-grid-v3.png`
- `.evolve/tangle-cloud-design-audit-2026-06-07/mobile-blueprints-list-v3.png`
- `.evolve/tangle-cloud-design-audit-2026-06-07/mobile-blueprints-register-v3.png`
- `.evolve/tangle-cloud-design-audit-2026-06-07/desktop-ai-agent-deploy-v2.png`
- Deployment: not requested.
- Live proof: local dev server at `http://127.0.0.1:4210` with polling due system watcher limit.

## Next Pass
- Add a richer disconnected deploy preview that shows blueprint identity, operators, and trust before wallet connect.
- Consider moving route context out of the fixed topbar in a broader app-shell pass.
- Add a configured testnet Envio endpoint to avoid expected fallback warnings during local browsing.
57 changes: 57 additions & 0 deletions .evolve/tangle-cloud-design-audit-2026-06-08.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
# Tangle Cloud Design Audit - 2026-06-08

Status: implemented and browser verified on `feat/tangle-cloud-tangle-dapp-system`.

## Verdict

The Blueprints page moved from glass-on-glass catalog cards to a list-first infrastructure console that matches the original Tangle dapp's operational hierarchy while keeping Cloud-specific density. The remaining surface is not a marketing hero; it is a service catalog for deployers, operators, and publishers.

## Problems Addressed

- Duplicate Blueprints title in top nav and page header.
- Separate nav/title layer doing no unique work.
- Blueprints catalog readability at roughly 6/10: same-background cards, weak hierarchy, small labels, hidden wallet address, italic controls, and decorative button dots.
- Missing default blueprint visual identity for chain-only blueprints.
- Local preview defaulting to Anvil and firing localhost RPC/indexer calls while the UI showed Base Sepolia.
- Blueprint data refetching felt uncached after leaving and returning to the page.
- Add-capacity/register flow could look blank or broken.

## Product Direction

- Use the original Tangle dapp design system selectively: wallet/network affordances, compact chrome, crisp borders, action hierarchy, and restrained Tangle color accents.
- Keep Cloud as an infrastructure console: list/table first, cards only for repeated catalog/mobile/modals, no hero marketing treatment.
- Make Blueprints read like inventory: capacity, trust, source, usage, and actions are first-order columns.

## Changes Shipped

- Removed the `/blueprints` top-nav breadcrumb title and let the page own the large `Blueprints` heading.
- Kept wallet connection visible in the top-right shell and made the connected-address affordance visible.
- Forced network/action controls to normal font style and removed button pseudo-dot artifacts.
- Added default blueprint visuals for chain-only catalog rows/cards.
- Added list-first catalog layout with metrics, availability filters, category/filter controls, grid/list toggle, pagination, and mobile cards.
- Added React Query stale/cache behavior for blueprint queries.
- Normalized Cloud's local-preview network to Base Sepolia unless `VITE_FORCE_LOCAL_CHAIN=true`.
- Moved network normalization before indexer health checks and aligned audited-status reads with the selected Cloud network.
- Made the local sandbox `Button` wrapper forward refs for Radix `asChild` compatibility.
- Tightened the add-capacity drawer into a true right-side panel.
- Stubbed `window.scrollTo` in shared Vitest setup to remove noisy route-test output.

## Verification

- `NX_DAEMON=false NX_SKIP_NX_CACHE=true yarn nx typecheck tangle-cloud`
- `NX_DAEMON=false NX_SKIP_NX_CACHE=true yarn nx test tangle-cloud`
- `NX_DAEMON=false NX_SKIP_NX_CACHE=true yarn nx build tangle-cloud`
- Playwright screenshots and console checks:
- `/tmp/tangle-cloud-dapp-system-audit/blueprints-desktop-dark.png`
- `/tmp/tangle-cloud-dapp-system-audit/blueprints-desktop-light.png`
- `/tmp/tangle-cloud-dapp-system-audit/blueprints-mobile-dark.png`
- `/tmp/tangle-cloud-dapp-system-audit/instances-desktop-dark.png`
- `/tmp/tangle-cloud-dapp-system-audit/blueprints-add-capacity-flow.png`

Final browser counters:

- `local8545`: 0
- `local8080`: 0
- Radix ref warnings: 0
- italic controls: 0
- measured overflow: 0
3 changes: 2 additions & 1 deletion apps/tangle-cloud/PRODUCT_BRIEF.md
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ Primary actions: Connect wallet, switch network, create service, register operat

Trust, risk, and compliance: Money, permissions, and protocol identity must be exact, copyable, and auditable. Destructive or irreversible actions need clear state, provenance, and confirmation. Embedded apps must expose origin, permissions, denied actions, and unavailable bridge methods. Empty/error/loading states must be truthful and actionable.

Design posture: Dense infrastructure console with restrained blueprint identity accents. Use compact tables, split workspaces, tabs, ledgers, event timelines, thin borders, and low-chroma status colors. Cards belong mainly to catalog discovery, repeated items, and modals.
Design posture: Dense infrastructure console with restrained blueprint identity accents. Use compact tables, split workspaces, tabs, ledgers, event timelines, thin borders, and low-chroma status colors. Cards belong mainly to catalog discovery, repeated items, and modals. Cloud should inherit the original Tangle dapp's wallet, network, chrome, and action hierarchy where it improves operator trust, but keep Cloud pages data-first rather than marketing-first.

Non-goals: Do not reskin this as the AI trading app. Do not make a marketing landing page, decorative hero wall, app-store gallery, or purple/glow-heavy SaaS dashboard. Do not duplicate sidebar, topbar, breadcrumbs, page headers, tabs, and local nav unless each layer has a distinct job.

Expand All @@ -39,6 +39,7 @@ Evidence:
- `src/pages/services/[id]/page.tsx` mixes service console, blueprint presentation, ACL, jobs, billing, and upgrade surfaces in one vertical stack.
- `src/pages/blueprints/[id]/deploy/page.tsx` submits a request but sends users back to blueprint detail instead of request/service status.
- Parallel audit reports on 2026-06-05 converged on app/workspace-first IA and infrastructure-console visual direction.
- 2026-06-08 design-system pass restored Tangle dapp-style wallet/network affordances, removed the duplicate Blueprints nav title, converted the catalog to a list-first operator-capacity surface, added blueprint default visuals, and browser-verified desktop/mobile/light/dark render states.

Open questions:

Expand Down
9 changes: 6 additions & 3 deletions apps/tangle-cloud/src/app/CreditsProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,15 @@ export const CreditsProvider: FC<PropsWithChildren> = ({ children }) => {
: undefined;

useEffect(() => {
setCreditAccounts([]);
setIsLoading(true);
const gen = ++genRef.current;
queueMicrotask(() => {
if (genRef.current === gen) {
setCreditAccounts([]);
setIsLoading(Boolean(address));
}
});

if (!address) {
setIsLoading(false);
return;
}

Expand Down
11 changes: 8 additions & 3 deletions apps/tangle-cloud/src/app/ShieldedProvider.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,19 @@ export const ShieldedProvider: FC<PropsWithChildren> = ({ children }) => {
const [isReady, setIsReady] = useState(false);
const storageRef = useRef<IndexedDbNoteStorage | null>(null);
const notesRef = useRef(notes);
notesRef.current = notes;
// Sequential write queue to prevent concurrent persist() from losing notes
const writeQueueRef = useRef<Promise<void>>(Promise.resolve());

useEffect(() => {
notesRef.current = notes;
}, [notes]);

useEffect(() => {
// Reset synchronously to prevent stale data flash
setNotes([]);
setIsReady(false);
queueMicrotask(() => {
setNotes([]);
setIsReady(false);
});
// Flush the write queue so no pending writes leak to the new address
writeQueueRef.current = Promise.resolve();

Expand Down
36 changes: 28 additions & 8 deletions apps/tangle-cloud/src/app/providers.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -3,23 +3,43 @@ import { ToastProvider } from '@tangle-network/sandbox-ui/primitives';
import useLocalChainGuard from '@tangle-network/tangle-shared-ui/hooks/useLocalChainGuard';
import useNetworkSync from '@tangle-network/tangle-shared-ui/hooks/useNetworkSync';
import { IndexerStatusProvider } from '@tangle-network/tangle-shared-ui/context/IndexerStatusContext';
import useNetworkStore from '@tangle-network/tangle-shared-ui/context/useNetworkStore';
import { isLocalPreviewHost } from '@tangle-network/tangle-shared-ui/utils/localPreview';
import { FC, type PropsWithChildren, useEffect, useState } from 'react';
import { WagmiProvider } from 'wagmi';
import {
ANVIL_LOCAL_NETWORK,
BASE_SEPOLIA_NETWORK,
TANGLE_CLOUD_NETWORKS,
} from '../constants/networks';
import { cloudWagmiConfig } from './cloudWagmiConfig';
import PaymentProviders from './PaymentProviders';

// Component to sync network store with wagmi chain
const NetworkSync: FC<PropsWithChildren> = ({ children }) => {
const forceLocalChain = import.meta.env.VITE_FORCE_LOCAL_CHAIN === 'true';
const selectedNetwork = useNetworkStore((store) => store.network2);
const setNetwork = useNetworkStore((store) => store.setNetwork);

const needsCloudNetworkReset =
!forceLocalChain &&
selectedNetwork?.evmChainId === ANVIL_LOCAL_NETWORK.evmChainId;

useEffect(() => {
if (needsCloudNetworkReset) {
setNetwork(BASE_SEPOLIA_NETWORK);
}
}, [needsCloudNetworkReset, setNetwork]);

useNetworkSync(TANGLE_CLOUD_NETWORKS);
useLocalChainGuard({
enabled: isLocalPreviewHost(),
enabled: forceLocalChain && isLocalPreviewHost(),
targetChainId: ANVIL_LOCAL_NETWORK.evmChainId ?? 31337,
});
if (needsCloudNetworkReset) {
return null;
}

return children;
};

Expand Down Expand Up @@ -59,14 +79,14 @@ const Providers: FC<PropsWithChildren> = ({ children }) => {
reconnectOnMount={reconnectOnMount}
>
<QueryClientProvider client={queryClient}>
<IndexerStatusProvider>
<ToastProvider>
<ToastAccessibilityPatch />
<NetworkSync>
<NetworkSync>
<IndexerStatusProvider>
<ToastProvider>
<ToastAccessibilityPatch />
<PaymentProviders>{children}</PaymentProviders>
</NetworkSync>
</ToastProvider>
</IndexerStatusProvider>
</ToastProvider>
</IndexerStatusProvider>
</NetworkSync>
</QueryClientProvider>
</WagmiProvider>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,11 +72,31 @@ const useParentTheme = (): 'light' | 'dark' => {
// - allow-forms: required for normal form interactions inside the iframe.
// - allow-popups[-to-escape-sandbox]: gated on the manifest's allowPopups
// flag because they widen attack surface (oauth flows commonly need them).
// - allow-same-origin: gated on allowSameOrigin AND only when the app is
// CROSS-ORIGIN to us. Cross-origin + allow-same-origin restores the iframe's
// OWN origin (so embedded apps running their own wallet get the localStorage/
// IndexedDB WalletConnect needs) while cross-origin policy still blocks it
// from reaching our DOM/storage. We refuse it for same-origin apps, since
// same-origin + allow-scripts would let the frame remove its own sandbox.
const isCrossOrigin = (origin: string): boolean => {
if (typeof window === 'undefined') {
return false;
}
try {
return new URL(origin).origin !== window.location.origin;
} catch {
return false;
}
};

const buildSandbox = (config: BlueprintIframeConfig): string => {
const tokens = ['allow-scripts', 'allow-forms'];
if (config.allowPopups) {
tokens.push('allow-popups', 'allow-popups-to-escape-sandbox');
}
if (config.allowSameOrigin && isCrossOrigin(config.origin)) {
tokens.push('allow-same-origin');
}
return tokens.join(' ');
};

Expand Down
Loading
Loading