# Veilbooks Sketch UX Spec

Source sketches:

- `Veilbooks Landing page.pdf`
- `Veilbooks Wallet connect page.pdf`
- `Veilbooks Home page.pdf`
- `Veilbooks sidebar.pdf`
- `Veilbooks AR and AP aging summary page.pdf`
- `Veilbooks invoice page.pdf`

## 1. Sketch Interpretation

### Visible Screens

- Observed: Landing or unauthenticated home screen with Veilbooks brand, centered logo area, "Private Invoicing powered by Railgun", a top-right connect wallet button, and a Docs link.
- Observed: Wallet connection screen with Veilbooks brand, a centered wallet provider panel, and a top-right connected wallet display after success.
- Observed: Authenticated home dashboard with sidebar, global search, shielded balance card, accounts receivable/payable summary cards, and a Create Invoice CTA.
- Observed: Sidebar navigation with Home, Create invoice, Accounts receivable, Accounts payable, aging summary links, and placeholder links.
- Observed: Accounts receivable aging summary table. The accounts payable view is implied by the same sketch filename and sidebar structure.
- Observed: Invoice creation page with customer selector, invoice metadata fields, item table, customer note, subtotal, shipping, and invoice total.

### Layout Regions

- Observed: Brand sits in the upper left on public pages and inside the left app rail on authenticated pages.
- Observed: Wallet connection or connected wallet identity sits in the upper right.
- Observed: Dashboard uses a left sidebar, top search region, central balance summary, lower AR/AP summary cards, and a bottom Create Invoice button.
- Observed: Aging summary uses a full-width table with vendor/customer rows and aging bucket columns.
- Observed: Invoice editor uses a top metadata area, a line-item grid, a note box, and a right-aligned totals panel.

### User Actions

- Observed: Connect wallet.
- Observed: Pick a wallet provider from the connection panel.
- Observed: Search transactions, contacts, and reports.
- Observed: View private token balances.
- Observed: Open accounts receivable or accounts payable.
- Observed: Open aging summary pages.
- Observed: Create invoice.
- Observed: Select a customer, set terms and dates, add invoice line items, enter shipping, and review invoice total.
- Inferred: Use a viewing key to pull private transaction/payment data for AR/AP aging.
- Inferred: Click token rows or logos to view per-token private balance detail.
- Inferred: Submit or issue an invoice after completing the invoice editor, though the submit button is not drawn.

### Likely Flow Order

1. Landing page -> user selects Connect wallet.
2. Wallet connect page -> user chooses a provider and signs/approves connection.
3. Authenticated dashboard -> user sees connected 0zk wallet, synced shielded balances, search, AR/AP summaries, and invoice CTA.
4. User either creates an invoice or reviews receivables/payables.
5. Aging summary pages pull private invoice/payment transactions using the user's viewing key.
6. Invoice page lets the user compose invoice details and totals, then should move to review and issue/send states.

### Repeated Components

- App shell with sidebar and top-right wallet identity.
- Wallet badge and connect wallet control.
- Search or command input.
- Card surfaces for balances and AR/AP summaries.
- Data tables for balances, aging summaries, and invoice line items.
- Date picker fields.
- Amount fields and totals panels.
- Empty, loading, syncing, failed, and completed transaction states.

### Ambiguous Or Unclear Areas

- Unclear: The wallet provider button labels are partially legible. Treat them as provider options until exact connector names are known.
- Unclear: Aging bucket text appears to include current, 1-30 days, 31-60 days, and a final older bucket. Production should use explicit buckets: Current, 1-30, 31-60, 61-90, 91+, Total, unless the accounting model requires fewer columns.
- Unclear: Whether the dashboard token rows show public wallet balances, private balances, or both. The title says Shielded Balance, so default to private/shielded balances.
- Unclear: The sidebar contains "place holder" entries under AR/AP. Treat these as future subpages and hide or label them clearly in production.
- Unclear: The invoice page does not show final actions. Add Save draft, Preview, and Review invoice as the production defaults.

### Assumptions And Sensible Defaults

- Assumption: Veilbooks is a privacy-preserving invoicing app powered by 0zk/Railgun-style private balances and private payment visibility.
- Assumption: The user connects a wallet before any private balance, invoice payment, or aging-summary data is shown.
- Assumption: Viewing-key sync is needed for balance and payment history, and the UI should disclose sync status without exposing cryptographic jargon.
- Assumption: Invoice creation can be drafted without broadcasting a payment transaction, but issuing or collecting payment should have a review step.
- Assumption: The app should support empty-state demo data, skeleton loading, sync-progress states, and retry states for wallet and private transaction reads.

## 2. Screen-by-Screen UX Spec

### Landing Page

- Screen purpose: Introduce Veilbooks and route users into wallet connection.
- Primary user goal: Understand the product enough to connect a wallet.
- Component hierarchy: `PublicHeader`, `BrandMark`, `ConnectWalletButton`, `HeroLogo`, `HeroCopy`, `DocsLink`.
- Main actions: Connect wallet.
- Secondary actions: Open Docs.
- Required data: Wallet connection status.
- Empty states: None.
- Loading states: Connect button shows `connecting`.
- Pending states: Wallet modal open; provider request pending.
- Rejected states: Wallet request rejected with "Connection was not approved. Try again when ready."
- Error states: Wallet unavailable, unsupported browser, or provider failure.
- Success states: Route to dashboard after connection and initial account lookup.
- Completed states: Connected wallet badge replaces public connect CTA.
- Mobile behavior: Header becomes a compact top bar; hero content remains first screen with connect CTA visible.
- Accessibility notes: `main` landmark, H1 "Veilbooks", button has visible label, wallet errors announced with `aria-live`.

### Wallet Connect Page

- Screen purpose: Let users choose a wallet/provider and confirm connection.
- Primary user goal: Connect the correct wallet and enter the app.
- Component hierarchy: `PublicHeader`, `WalletConnectPanel`, `WalletProviderOption`, `WalletStatusMessage`, `ConnectedWalletPreview`.
- Main actions: Select wallet provider, approve connection.
- Secondary actions: Cancel, retry, view Docs.
- Required data: Supported providers, provider availability, wallet address, connection status, selected network.
- Empty states: No detected wallets, with install/help link.
- Loading states: Provider list loading; wallet request pending.
- Pending states: Awaiting wallet approval.
- Rejected states: User rejects wallet approval.
- Error states: Wallet locked, unsupported network, provider unavailable, wrong account.
- Success states: Top-right wallet badge displays shortened 0zk address or connected account.
- Completed states: Redirect to dashboard with wallet persisted.
- Mobile behavior: Provider choices become full-width rows; modal can become a bottom sheet.
- Accessibility notes: Focus moves into dialog, Esc closes when safe, provider options are keyboard-selectable.

### Home Dashboard

- Screen purpose: Provide a private finance overview and entry points into invoice/account workflows.
- Primary user goal: See shielded balances, find records, and create or review invoices.
- Component hierarchy: `AppShell`, `SidebarNav`, `TopSearch`, `WalletBadge`, `PrivateBalanceCard`, `TokenBalanceRow`, `AccountsSummaryCards`, `CreateInvoiceButton`.
- Main actions: Search, create invoice, open AR/AP summaries, inspect token balance.
- Secondary actions: Open contacts, reports, wallet details, token detail, activity history.
- Required data: Wallet address, network, private balance sync status, token balances, supported token metadata, AR/AP counts/totals.
- Empty states: "No private balances yet" with Shield funds CTA; no AR/AP records with Create invoice CTA.
- Loading states: Skeleton rows for balances and summary cards.
- Pending states: Syncing private balances with phase text such as "Scanning private activity".
- Rejected states: Wallet disconnected or viewing-key approval rejected.
- Error states: Wrong network, sync failed, stale balance, unsupported token.
- Success states: Shielded balance total and token rows are visible.
- Completed states: Last synced time and ready status visible.
- Mobile behavior: Sidebar collapses to drawer; balance card becomes full width; Create Invoice is sticky at bottom.
- Accessibility notes: Balance amounts have text equivalents; token logos are decorative with accessible token names in rows.

### Sidebar Navigation

- Screen purpose: Provide persistent workflow navigation.
- Primary user goal: Move between home, invoice creation, receivables, and payables.
- Component hierarchy: `SidebarNav`, `NavItem`, `NavSection`, `SubNavItem`, `SidebarCollapseButton`.
- Main actions: Home, Create invoice, Accounts receivable aging summary, Accounts payable aging summary.
- Secondary actions: Placeholder/future links should be hidden, disabled with clear label, or replaced with actual pages.
- Required data: Current route, unread/pending counts, collapsed state.
- Empty states: None.
- Loading states: Counts can skeleton-load.
- Pending states: Route change pending.
- Rejected states: None.
- Error states: Unauthorized route access returns to wallet connect.
- Success states: Active route is highlighted and announced.
- Completed states: Nav state persists across refresh.
- Mobile behavior: Sidebar becomes sheet/drawer with focus trap.
- Accessibility notes: Use `nav` landmark, `aria-current="page"` on active link, keyboard-friendly nested links.

### Accounts Receivable Aging Summary

- Screen purpose: Show outstanding customer/vendor receivables grouped by age.
- Primary user goal: Identify unpaid or late receivables.
- Component hierarchy: `AgingSummaryPage`, `AgingSummaryToolbar`, `ViewingKeySyncStatus`, `AgingSummaryTable`, `AgingBucketCell`, `AgingTotalsRow`.
- Main actions: Sync private activity, filter by customer/vendor, open record detail.
- Secondary actions: Export CSV, copy report, switch to payables, view advanced sync details.
- Required data: Account name, current amount, 1-30, 31-60, 61-90, 91+, total, viewing-key sync status, last sync time.
- Empty states: No receivables found; offer Create invoice.
- Loading states: Table skeleton and sync timeline.
- Pending states: Viewing-key scan in progress; balances may be stale.
- Rejected states: User declines viewing-key or wallet signature required for sync.
- Error states: Sync failed, unsupported network, no viewing key, stale data warning.
- Success states: Rows show aging buckets and totals.
- Completed states: Report shows last synced timestamp and final totals.
- Mobile behavior: Use a horizontally scrollable table with sticky account column and totals; provide card view for very narrow screens.
- Accessibility notes: Use semantic table headers, numeric values right-aligned, status not color-only.

### Accounts Payable Aging Summary

- Screen purpose: Show bills or outgoing invoice obligations grouped by age.
- Primary user goal: Identify upcoming and overdue payables.
- Component hierarchy: Same as receivables with `mode="payable"`.
- Main actions: Sync, filter, open payable detail, pay/review payable when supported.
- Secondary actions: Export, switch to receivables, view sync details.
- Required data: Vendor, aging buckets, total, linked invoice/payment status.
- Empty states: No payables found.
- Loading states: Table skeleton.
- Pending states: Private activity sync or pending payable payment.
- Rejected states: Wallet/viewing-key approval rejected.
- Error states: Sync failed, unsupported network, stale payment status.
- Success states: Payables aging data visible.
- Completed states: Totals reconcile with payable summary card.
- Mobile behavior: Same as receivables.
- Accessibility notes: Same as receivables.

### Invoice Creation Page

- Screen purpose: Compose an invoice for a customer.
- Primary user goal: Build a correct invoice and review it before sending or saving.
- Component hierarchy: `InvoiceEditorPage`, `CustomerSelector`, `InvoiceMetadataFields`, `InvoiceLineItemsTable`, `CustomerNoteField`, `InvoiceTotalsPanel`, `InvoiceActionsBar`.
- Main actions: Select customer, add/edit line items, set dates/terms, save draft, review invoice.
- Secondary actions: Preview invoice, duplicate line, remove line, add shipping, cancel.
- Required data: Customer, invoice number, terms, invoice date, due date, product/service, service date, description, quantity, rate, amount, note, subtotal, shipping, total.
- Empty states: Blank invoice with first editable line item.
- Loading states: Customer list loading; invoice draft restoring.
- Pending states: Draft saving; invoice review generation.
- Rejected states: User cancels review or wallet signature if issuing requires signing.
- Error states: Missing customer, invalid dates, negative quantity/rate, total mismatch, save failed.
- Success states: Draft saved or invoice ready for review.
- Completed states: Invoice issued/sent, with link to invoice detail and activity/history.
- Mobile behavior: Metadata fields stack; line items become editable cards; totals panel is sticky below items.
- Accessibility notes: Every input has visible label; table edit order is logical; totals update announced politely.

## 3. Design Improvements

- Visual hierarchy: Keep a quiet accounting-app layout. Use the dashboard balance card as the primary object, AR/AP summaries as secondary objects, and Create Invoice as the main workflow CTA.
- Calls-to-action: Use specific labels: "Connect wallet", "Sync private activity", "Create invoice", "Review invoice", "Save draft", "Open receivables", "Open payables".
- Transaction confirmation safety: Any shield, private payment, unshield, or invoice payment action must pass through a review panel before wallet signature.
- Labels and helper text: Replace generic "0zk..." with a shortened address plus network label, for example `0zk...91f2 - Ethereum`.
- Cognitive load: Hide placeholder sidebar entries until backed by real pages. Keep advanced protocol details inside drawers.
- Privacy explanations: Use plain copy such as "Veilbooks uses your viewing key to read private invoice payments for this wallet." Avoid absolute privacy promises.
- Spacing and grouping: Group invoice metadata on the right, customer on the left, line items in the center, and totals in the lower right, matching the sketch.
- Responsive layout: Collapse sidebar to drawer, preserve wallet/network status in the top bar, and keep invoice totals visible after line items on mobile.
- Progressive disclosure: Add "Advanced details" sections for network, viewing key, broadcaster/relayer status, transaction hash, and sync diagnostics.

## 4. 0zk / Railgun Flow Guidance

### Connect Wallet

- Preflight: Detect provider, wallet locked state, connected account, selected network, supported network, and existing session.
- States: `disconnected`, `connecting`, `connected`, `rejected`, `locked_wallet`, `wrong_network`, `unsupported_network`.
- Recovery: Offer retry, switch network, unlock wallet, or change provider.

### Select Network

- Keep network visible before private actions.
- If network is unsupported, block private balances, shield/send/pay actions, and show "Switch network" as the primary action.
- Store network in dashboard state and include it in review panels.

### View Shielded Balances

- Preflight: Connected wallet, supported network, viewing-key access, private balance sync readiness.
- States: `needs_wallet`, `needs_viewing_key`, `syncing`, `stale`, `ready`, `failed`.
- Empty state: "No shielded balance yet" with a Shield funds CTA if shielding is in scope.
- Advanced detail: Last sync time, token contract, chain ID, and scan status.

### Shield Asset

- If added to this app, separate token approval from shielding.
- Review panel must show amount, token, source public wallet, destination private balance, network, fee estimate, and what the wallet signature authorizes.
- Timeline: validating -> approval if needed -> awaiting signature -> preparing -> broadcasting -> confirming -> syncing balance -> complete.

### Send Or Pay Privately

- For invoice payment, review recipient/customer, invoice number, token, amount, network, fee estimate, and finality before signing.
- Keep payment amount separate from network/broadcaster costs.
- After payment, link to invoice activity and AR/AP aging rows.

### Review Transaction

- Required before any action that moves funds, reveals funds, or changes invoice payment state.
- Show editable fields, plain-language privacy note, fee estimate, and an advanced drawer.
- Do not use generic CTAs. Use "Review private payment", "Pay invoice privately", or "Shield USDC".

### Confirm Wallet Signature

- Explain what the signature authorizes in one sentence.
- Show `awaiting_signature`; if rejected, say no funds moved unless an earlier approval already completed.

### Pending And Private Transaction Status

- Use a timeline instead of a spinner: preparing, awaiting signature, broadcasting, confirming, syncing private activity, complete.
- For long syncs, keep the invoice/payment visible and mark data as pending or stale rather than blanking the screen.

### Fees, Broadcaster, And Relayer Behavior

- Separate invoice amount from network fee and broadcaster/relayer cost.
- Label fees as estimates until confirmed.
- Advanced drawer can show fee source, broadcaster/relayer status, transaction hash, and confirmation count.

### Failure And Recovery

- Wallet rejection: Let the user retry from the same state.
- Wrong network: Primary CTA is Switch network.
- Insufficient balance or fee coverage: Show required amount and token.
- Sync failure: Keep last known values, mark them stale, and offer Retry sync.
- Transaction timeout: Explain whether the transaction was broadcast and link to activity details.

### Activity History

- Link completed, pending, failed, and rejected invoice/payment actions to an activity view.
- Activity rows should include invoice/customer, token, amount, network, status, timestamp, and a details drawer.

## 5. Implementation-Ready Plan

### Route Outline

- `/` - landing page.
- `/connect` - wallet provider selection and connection recovery.
- `/app` - authenticated home dashboard.
- `/app/invoices/new` - invoice editor.
- `/app/accounts/receivable/aging` - receivables aging summary.
- `/app/accounts/payable/aging` - payables aging summary.
- `/app/activity` - private transaction and invoice activity history.

### Component Outline

- `PublicHeader`
- `ConnectWalletButton`
- `WalletConnectPanel`
- `WalletProviderOption`
- `WalletBadge`
- `NetworkSelector`
- `AppShell`
- `SidebarNav`
- `GlobalSearchCommand`
- `PrivateBalanceCard`
- `TokenBalanceRow`
- `AccountsSummaryCard`
- `AgingSummaryTable`
- `ViewingKeySyncStatus`
- `InvoiceEditorPage`
- `CustomerSelector`
- `InvoiceMetadataFields`
- `InvoiceLineItemsTable`
- `InvoiceTotalsPanel`
- `InvoiceActionsBar`
- `TransactionReviewPanel`
- `TransactionStatusTimeline`
- `AdvancedPrivacyDetails`
- `ActivityHistoryList`

### Suggested UI Primitives

- Dialog or Drawer: wallet connection, transaction review, advanced details on mobile.
- Select or Combobox: wallet provider, customer, token, terms.
- Popover: date picker.
- Table: aging summaries and desktop invoice line items.
- Toast: save draft, sync complete, copied/exported.
- AlertDialog: irreversible private payment or unshield confirmation.
- Tooltip: token logos, sync status, fee details.

### State Model

- Wallet: `disconnected`, `connecting`, `connected`, `rejected`, `locked_wallet`, `wrong_network`, `unsupported_network`.
- Private balance: `idle`, `needs_wallet`, `needs_viewing_key`, `syncing`, `stale`, `ready`, `failed`.
- Invoice editor: `draft`, `dirty`, `validating`, `ready_for_review`, `saving`, `saved`, `failed`.
- Private transaction: `idle`, `validating`, `needs_approval`, `ready_for_review`, `awaiting_signature`, `preparing`, `broadcasting`, `confirming`, `syncing`, `completed`, `rejected`, `failed`, `timed_out`.

### Data Requirements

- Wallet: address, display address, provider, network, chain ID, connection state.
- Token: symbol, logo, decimals, private balance, fiat estimate, supported network, stale flag.
- Aging row: counterparty ID/name, type `receivable` or `payable`, current, 1-30, 31-60, 61-90, 91+, total, linked invoice count.
- Invoice: ID, customer, invoice number, terms, invoice date, due date, line items, customer note, subtotal, shipping, total, status.
- Activity: ID, invoice ID, token, amount, network, status, phase, timestamp, transaction hash if available, advanced diagnostic fields.

### Tailwind Layout Structure

- App shell: `grid min-h-screen grid-cols-[260px_1fr]` on desktop; drawer sidebar below `lg`.
- Dashboard content: `mx-auto grid w-full max-w-6xl gap-6 px-6 py-6`.
- Balance card: fixed header plus token rows, using stable row heights to avoid layout shift during sync.
- Aging table: `overflow-x-auto` wrapper, sticky first column, right-aligned numeric cells.
- Invoice editor: `grid grid-cols-[1fr_320px] gap-6` on desktop; single column on mobile with sticky action bar.

### Acceptance Criteria

- Landing page shows Veilbooks, product value copy, Docs link, and wallet CTA on mobile and desktop.
- Wallet connect covers disconnected, connecting, connected, rejected, locked, wrong-network, and unsupported-network states.
- Dashboard never shows private balance data without a connected wallet and supported network.
- Private balance card distinguishes loading, syncing, stale, empty, failed, and ready states.
- AR/AP aging tables use semantic headers and maintain readable totals on mobile.
- Invoice editor validates required customer, invoice number, valid dates, line item quantity/rate, and total calculations.
- Review is required before any invoice payment, shield, private send, or unshield action.
- Transaction timeline distinguishes wallet rejection, failed transaction, pending confirmation, and completed sync.
- Keyboard navigation works through wallet dialog, sidebar, search, invoice fields, review panel, and drawers.
- Text, buttons, and table cells do not overlap at 320px, tablet, and desktop widths.

### Test Notes

- Unit test invoice total calculation, date validation, aging bucket mapping, and wallet state transitions.
- Component test wallet connect recovery states and private balance sync states.
- Accessibility test semantic tables, visible labels, focus trap, `aria-live` status changes, and keyboard order.
- Responsive visual test dashboard, aging table, sidebar drawer, and invoice editor at mobile and desktop widths.
- Transaction-state test review -> signature -> pending -> completed, rejection recovery, failed sync, and stale data display.
