| type | Feature |
|---|---|
| title | Replace mock invoice data on the Invest marketplace with a live backend API client |
| labels | type:feature, area:invest, stack:nextjs, stack:react, stack:typescript, priority:high, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN |
| assignees |
The Invest marketplace in app/invest/page.js renders three hard-coded entries from the local MOCK_INVOICES array via loadMockInvoices(), with a DEV_DELAY timer simulating latency. There is no shared API client anywhere in the repo, even though README.md and .env.local.example define NEXT_PUBLIC_API_URL. This issue replaces the mock loader with a real fetch-based client that pulls investable invoices from the backend while preserving the existing loading, empty, and error states.
- Repository scope: Liquifact/Liquifact-frontend only.
- Create
lib/api/invoices.jsexportingfetchInvestableInvoices({ signal })that calls${NEXT_PUBLIC_API_URL}/invoicesand normalizes the response into the existing item contract{ id, issuer, amount, currency, dueDate, yield, status }. - Wire
InvestMarketplaceto use the new client by passing it as theloadInvoicesprop default, keeping the injectable-prop pattern used byapp/invest/page.test.jsxintact. - Preserve the existing
null(loading), empty, andloadErrorbranches and thearia-livestatus announcement fromgetInvoiceLoadAnnouncement. - Use
AbortControllerso in-flight requests are cancelled when the component unmounts (the effect already tracksisActive). - Read the base URL from
process.env.NEXT_PUBLIC_API_URLwith thehttp://localhost:3001fallback, matchingapp/page.js.
- Fork the repo and create a branch
git checkout -b feature/invest-01-live-invoice-api-client- Implement changes
- Write code in: create
lib/api/invoices.jsand updateapp/invest/page.js. - Write comprehensive tests in: create
lib/api/invoices.test.tsxand extendapp/invest/page.test.jsxβ mockfetch, assert normalization, abort behaviour, and error fallback. - Add documentation: update
README.mdwith the newlib/apilayer and document the/invoicesresponse shape. - Add JSDoc to every exported function describing params, return shape, and thrown errors.
- Validate security: never interpolate unvalidated data into the DOM, and guard against non-array/
nullresponses.
- Write code in: create
- Test and commit
- Run
npm run lint,npm test, andnpm run build. - Cover edge cases: non-200 responses, malformed JSON, empty arrays, network failure, and unmount-during-fetch.
- Include the full
npm testoutput and a short note on how the mock loader was retired.
feat: replace invest marketplace mock data with live backend api client
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord for questions, reviews, and faster merges: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Wire the UploadZone invoice submission to a real upload endpoint" labels: type:feature, area:upload, stack:nextjs, stack:react, stack:typescript, priority:high, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
components/UploadZone.jsx validates a PDF and then fakes the upload by stepping through uploading β tokenizing β success with two setTimeout(1500) calls β no network request is ever made. This issue replaces the simulated flow with a real multipart upload to the backend while keeping the existing status copy, spinner, and role="status" announcements that the Playwright spec in tests/toast.spec.jsx depends on.
- Repository scope: Liquifact/Liquifact-frontend only.
- Create
lib/api/upload.jsexportinguploadInvoice(file, { signal })that POSTs aFormDatabody to${NEXT_PUBLIC_API_URL}/invoicesand returns the created invoice id/status. - Replace the two
await new Promise((r) => setTimeout(...))blocks inhandleSubmitwith the real request, mapping HTTP/network failures to the existingerrorstate androle="alert"banner. - Preserve the
FILE_CONSTRAINTSvalidation, thestatusstate machine, and the disabled/aria-disabledlogic on#invoice-upload-btn. - Keep success copy "Invoice queued for tokenization. Blockchain confirmation pending." so the existing e2e assertion still passes.
- Surface failures through the existing
ToastProvider(seecomponents/ToastProvider.jsx) in addition to the inline banner.
- Fork the repo and create a branch
git checkout -b feature/upload-02-real-upload-endpoint- Implement changes
- Write code in: create
lib/api/upload.jsand updatecomponents/UploadZone.jsx. - Write comprehensive tests in: extend
components/UploadZone.test.jsxand createlib/api/upload.test.tsxβ mockfetch, assert FormData shape, success transition, and error mapping. - Add documentation: update
README.mdand cross-referenceWALLET_INTEGRATION_CONTRACT.mdwhere relevant. - Add JSDoc on
uploadInvoicedescribing the request contract and error semantics. - Validate security: enforce the PDF MIME/size checks client-side before sending and never trust the filename for rendering.
- Write code in: create
- Test and commit
- Run
npm run lint,npm test,npm run build, andnpm run test:e2e. - Cover edge cases: 4xx/5xx responses, network failure mid-upload, double-submit prevention, and oversized file rejection before request.
- Include the full
npm testoutput and confirmation the Playwright toast spec still passes.
feat: wire uploadzone submission to a real invoice upload endpoint
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord for questions, reviews, and faster merges: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Mount the WalletStatus state machine in the app header and remove the dead Connect Wallet button" labels: type:feature, area:wallet, stack:nextjs, stack:react, stack:typescript, priority:high, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
components/WalletStatus.jsx is a complete six-state wallet UI (with toasts and accessible status announcements) but it is never rendered anywhere β every page ships its own static "Connect Wallet" <button> that does nothing, in app/page.js and app/invoices/page.js. This issue extracts a shared header and mounts WalletStatus so the wallet flow is actually reachable.
- Repository scope: Liquifact/Liquifact-frontend only.
- Create
components/AppHeader.jsxcontaining the LiquiFact wordmark/back link plus theWalletStatuscomponent, and use it inapp/page.js,app/invoices/page.js, and the marketplace header inapp/invest/page.js. - Remove the dead static buttons that currently use
copy.layout.connectWallet. - Preserve
WalletStatus's exportedWALLET_STATESand its existingrole="status"/aria-liveregions; the header must keep keyboard focus styles consistent with thefocus-visibleoutline already used on the invoices back link. - Keep the marketplace's "β LiquiFact" back-link semantics on non-home pages.
- Fork the repo and create a branch
git checkout -b feature/wallet-03-mount-walletstatus-header- Implement changes
- Write code in: create
components/AppHeader.jsx; updateapp/page.js,app/invoices/page.js, andapp/invest/page.js. - Write comprehensive tests in: create
components/AppHeader.test.tsxβ assert WalletStatus mounts, back link renders only off-home, and no stray static button remains. - Add documentation: update the "UI Components" section in
README.mdto documentAppHeader. - Add JSDoc/prop documentation for
AppHeader(e.g.showBackLink). - Validate a11y: header is a
<header>landmark with a single accessible name.
- Write code in: create
- Test and commit
- Run
npm run lint,npm test, andnpm run build. - Cover edge cases: home vs inner-page header variants and focus order through the wallet button.
- Include the full
npm testoutput and before/after notes on the removed dead buttons.
feat: mount walletstatus in a shared appheader and remove dead connect button
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord for questions, reviews, and faster merges: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Integrate Freighter wallet so WalletStatus connects to a real Stellar account" labels: type:feature, area:wallet, stack:nextjs, stack:react, stack:typescript, priority:high, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
components/WalletStatus.jsx simulates connection by picking a random outcome inside a setTimeout, with mockWalletData and a // replace with actual wallet integration comment. WALLET_INTEGRATION_CONTRACT.md specifies Freighter as the primary target and lists the required detection, connection, network-verification, and error paths. This issue replaces the mock with a real @stellar/freighter-api integration.
- Repository scope: Liquifact/Liquifact-frontend only.
- Create
lib/wallet/freighter.jswrapping detection (isConnected), connection request, account public key retrieval, and network detection. - Replace
connectWallet()/disconnectWallet()mock logic soWALLET_STATEStransitions reflect real outcomes:NO_WALLETwhen Freighter is absent,WRONG_NETWORKwhen on testnet while expecting public,ERRORon user rejection. - Populate
walletDatawith the contract shape{ address, network, balance, walletType }; format the balance and truncate the address for display as the UI already expects. - Read the expected network from
NEXT_PUBLIC_STELLAR_NETWORK(see commented entry in.env.local.example) defaulting totestnet. - Keep all existing accessibility regions and toast calls intact.
- Fork the repo and create a branch
git checkout -b feature/wallet-04-freighter-integration- Implement changes
- Write code in: create
lib/wallet/freighter.js; updatecomponents/WalletStatus.jsxand.env.local.example. - Write comprehensive tests in: create
components/WalletStatus.test.tsxβ mock the freighter wrapper for connect, reject, no-wallet, and wrong-network paths. - Add documentation: update
WALLET_INTEGRATION_CONTRACT.mdstatus checklist andREADME.mdsetup steps. - Add JSDoc to the wrapper functions; document the supported network env var.
- Validate security: verify the address format and network before any UI claims "connected".
- Write code in: create
- Test and commit
- Run
npm run lint,npm test, andnpm run build. - Cover edge cases: extension missing, user cancels, testnet mismatch, and rapid connect/disconnect.
- Include the full
npm testoutput and security notes on address/network validation.
feat: integrate freighter wallet for real stellar account connection
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord for questions, reviews, and faster merges: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Enable the disabled Invest marketplace filters (yield, currency, maturity, sort)" labels: type:feature, area:invest, stack:nextjs, stack:react, stack:typescript, priority:medium, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
The Invest page in app/invest/page.js renders Yield Range, Currency, Maturity Date, Sort, and Clear Filters as permanently disabled buttons with "Soon" badges. FILTER_CONTRACTS.md already documents the intended query-parameter contract for each. This issue makes the filters interactive and applies them to the invoice list client-side (and via query params once the API client exists).
- Repository scope: Liquifact/Liquifact-frontend only.
- Create
components/InvoiceFilters.jsximplementing the five controls fromFILTER_CONTRACTS.md, replacing the inline disabled markup. - Apply filtering/sorting to the loaded invoices in
InvestMarketplace; keepgetInvoiceLoadAnnouncementaccurate after filtering (announce filtered count). - Map control state to the documented query params (
yield_min,currency,maturity_from,sort, etc.) so the future API client can consume them. - Remove the
aria-label="... (coming soon)"strings and the "Soon" badges once controls are live. - Preserve responsive
flex-wraplayout and the slate/cyan styling.
- Fork the repo and create a branch
git checkout -b feature/invest-05-enable-marketplace-filters- Implement changes
- Write code in: create
components/InvoiceFilters.jsx; updateapp/invest/page.js. - Write comprehensive tests in: create
components/InvoiceFilters.test.tsxand extendapp/invest/page.test.jsx. - Add documentation: update
FILTER_CONTRACTS.mdto reflect the now-implemented controls and the README UI section. - Add JSDoc/prop docs for
InvoiceFilters(onChange,value). - Validate a11y: each control has an associated label and reflects pressed/selected state.
- Write code in: create
- Test and commit
- Run
npm run lint,npm test, andnpm run build. - Cover edge cases: empty results after filtering, clearing filters, and combined filter + sort.
- Include the full
npm testoutput and screenshots of active filter states.
feat: enable invest marketplace filters and sorting controls
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord for questions, reviews, and faster merges: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Add an invoice detail route with a fund-invoice action for investors" labels: type:feature, area:invest, stack:nextjs, stack:react, stack:typescript, priority:medium, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
The marketplace list items in app/invest/page.js render issuer, amount, yield, and maturity but are not clickable β there is no detail view and no way to express intent to fund. This issue adds an /invest/[id] route that shows full invoice details and a "Fund this invoice" call to action wired to the wallet flow.
- Repository scope: Liquifact/Liquifact-frontend only.
- Create
app/invest/[id]/page.jsrendering the invoice detail using the same{ id, issuer, amount, currency, dueDate, yield, status }contract. - Make each marketplace
<li>anext/linkto its detail route, preserving keyboard focusability. - Add a "Fund this invoice" button that prompts wallet connection (via the WalletStatus/Freighter flow) when disconnected and shows an educational disclaimer consistent with the existing yield-disclaimer note.
- Add
app/invest/[id]/loading.jsreusing the skeleton aesthetic fromapp/invest/loading.js. - Handle unknown ids with a friendly not-found state.
- Fork the repo and create a branch
git checkout -b feature/invest-06-invoice-detail-route- Implement changes
- Write code in: create
app/invest/[id]/page.jsandapp/invest/[id]/loading.js; updateapp/invest/page.js. - Write comprehensive tests in: create
app/invest/[id]/page.test.tsx. - Add documentation: update
README.mdproject structure with the new route. - Add JSDoc on any helper that resolves an invoice by id.
- Validate a11y: detail headings form a logical outline and the fund button has a clear accessible name.
- Write code in: create
- Test and commit
- Run
npm run lint,npm test, andnpm run build. - Cover edge cases: missing id, disconnected wallet click, and back navigation.
- Include the full
npm testoutput and notes on the funding intent flow.
feat: add invoice detail route with fund-invoice action
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord for questions, reviews, and faster merges: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Render a real uploaded-invoices list on the Invoices page instead of upload-only" labels: type:feature, area:invoices, stack:nextjs, stack:react, stack:typescript, priority:medium, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
app/invoices/page.js only renders an <UploadZone /> and intro copy; the README and copy.invoices.emptyState reference a list that does not yet exist. This issue adds a list of the SME's own invoices with their tokenization status below the upload zone, reusing the loading/empty/error patterns already established on the Invest page.
- Repository scope: Liquifact/Liquifact-frontend only.
- Create
components/InvoiceList.jsxthat renders the SME's invoices with status badges (e.g. Pending tokenization, Tokenized, Funded, Settled). - Add loading via
components/InvoiceListSkeleton.jsx, an empty state usingcopy.invoices.emptyState, and an error state usingcomponents/ErrorBanner.jsx. - Load data through the
lib/apiclient layer; until the backend exists, accept an injectable loader prop likeInvestMarketplacedoes for testability. - After a successful
UploadZonesubmission, optimistically refresh/append the new invoice.
- Fork the repo and create a branch
git checkout -b feature/invoices-07-uploaded-invoice-list- Implement changes
- Write code in: create
components/InvoiceList.jsx; updateapp/invoices/page.js. - Write comprehensive tests in: create
components/InvoiceList.test.tsx. - Add documentation: update the README UI section to document
InvoiceList. - Add JSDoc/prop docs (
loadInvoices, status enum). - Validate a11y: the list announces load completion via a polite live region like the marketplace.
- Write code in: create
- Test and commit
- Run
npm run lint,npm test, andnpm run build. - Cover edge cases: empty list, load error, and post-upload refresh.
- Include the full
npm testoutput and notes on the status enum.
feat: render uploaded-invoices list on the invoices page
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord for questions, reviews, and faster merges: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Add timeout, retry, and typed error handling to the home page API health check" labels: type:enhancement, area:home, stack:nextjs, stack:react, stack:typescript, priority:medium, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
The checkApi handler in app/page.js does a bare fetch(${API_URL}/health) with no timeout, no abort, and no handling for non-200 responses β a hung backend leaves the button stuck on "Checkingβ¦" indefinitely and res.json() can throw on an HTML error page. This issue makes the health check resilient with a timeout, abort, and structured success/error rendering.
- Repository scope: Liquifact/Liquifact-frontend only.
- Add an
AbortController-based timeout (e.g. 8s) so the request cannot hang forever. - Check
res.okbefore parsing and guardres.json()so non-JSON responses do not throw uncaught. - Render a clear connected/degraded/unreachable status rather than dumping raw JSON, while keeping a details disclosure for the raw payload.
- Move the URL/fetch logic into a shared helper in
lib/apiso it can be reused and unit-tested. - Keep the disabled-while-loading behaviour on the button.
- Fork the repo and create a branch
git checkout -b enhancement/home-08-health-check-hardening- Implement changes
- Write code in: update
app/page.js; create/extendlib/api/health.js. - Write comprehensive tests in: create
app/page.test.tsxandlib/api/health.test.tsxβ mockfetchfor ok, non-ok, timeout, and malformed JSON. - Add documentation: note the health-check behaviour in
README.md. - Add JSDoc on the health helper.
- Validate a11y: status changes are announced politely.
- Write code in: update
- Test and commit
- Run
npm run lint,npm test, andnpm run build. - Cover edge cases: timeout, 500 with HTML body, and offline.
- Include the full
npm testoutput.
feat: harden home page health check with timeout and typed errors
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord for questions, reviews, and faster merges: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Add a global App Router error boundary and not-found page" labels: type:feature, area:routing, stack:nextjs, stack:react, stack:typescript, priority:medium, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
The app has route-level loading.js files under app/invest/loading.js and app/invoices/loading.js but no error.js or not-found.js, so an unexpected render error or unknown URL falls back to Next.js defaults that clash with the dark slate/cyan theme. This issue adds branded error and 404 boundaries that reuse ErrorBanner.
- Repository scope: Liquifact/Liquifact-frontend only.
- Create
app/error.js(client component) usingcomponents/ErrorBanner.jsxwith a reset action and the dark theme background. - Create
app/not-found.jswith a link back home and consistent styling. - Optionally add
app/global-error.jsfor layout-level failures. - Reuse
copy/en.jsstrings; add any new copy keys there rather than inlining text.
- Fork the repo and create a branch
git checkout -b feature/routing-09-error-notfound-boundaries- Implement changes
- Write code in: create
app/error.js,app/not-found.js; updateapp/copy/en.js. - Write comprehensive tests in: create
app/error.test.tsxandapp/not-found.test.tsx. - Add documentation: document the boundaries in
README.md. - Add JSDoc on the reset handler.
- Validate a11y: error region uses
role="alert"(already in ErrorBanner) and 404 has a focusable home link.
- Write code in: create
- Test and commit
- Run
npm run lint,npm test, andnpm run build. - Cover edge cases: reset re-render and unknown route navigation.
- Include the full
npm testoutput.
feat: add global error boundary and branded not-found page
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord for questions, reviews, and faster merges: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Replace dead footer anchors with real navigation and external links" labels: type:enhancement, area:footer, stack:nextjs, stack:react, stack:typescript, priority:low, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
components/Footer.jsx renders Documentation, System Status, and Contact Support as href="#" placeholders with a {/* TODO: Add actual links when ready */} comment, so all three are dead clicks that scroll to the top. This issue wires them to real destinations and adds the Discord community link.
- Repository scope: Liquifact/Liquifact-frontend only.
- Replace the three
#anchors with real targets; external links must usetarget="_blank"withrel="noopener noreferrer". - Add a Discord community link pointing to https://discord.gg/JrGPH4V3.
- Source link labels/URLs from
app/copy/en.js(extendcopy.footer) rather than hard-coding. - Keep the existing focusable padding (
py-3) and hover styles for accessible tap targets.
- Fork the repo and create a branch
git checkout -b enhancement/footer-10-real-links- Implement changes
- Write code in: update
components/Footer.jsxandapp/copy/en.js. - Write comprehensive tests in: create
components/Footer.test.tsxβ assert hrefs,rel/targeton external links, and Discord link presence. - Add documentation: update the README footer component note.
- Add JSDoc on any link config.
- Validate security: every
target="_blank"carriesrel="noopener noreferrer".
- Write code in: update
- Test and commit
- Run
npm run lint,npm test, andnpm run build. - Cover edge cases: external vs internal links and keyboard focus order.
- Include the full
npm testoutput.
feat: replace dead footer anchors with real navigation links
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord for questions, reviews, and faster merges: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Add a skip-to-content link and consistent focus-visible styling across pages" labels: type:a11y, area:navigation, stack:nextjs, stack:react, stack:typescript, priority:medium, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
Only app/invoices/page.js defines focus-visible outlines; the home links in app/page.js and the marketplace back link in app/invest/page.js rely on default focus rings, and there is no skip-to-content link in app/layout.js. Keyboard and screen-reader users cannot quickly bypass the header. This issue adds a global skip link and standardizes focus styling.
- Repository scope: Liquifact/Liquifact-frontend only.
- Add a visually-hidden-until-focused "Skip to content" link as the first focusable element in
app/layout.js, targeting a#main-contentlandmark added to each page's<main>. - Add the existing cyan
focus-visibleoutline pattern to all interactive links/buttons that currently lack it. - Define reusable focus utilities/classes in
app/globals.cssso styling stays consistent. - Do not change layout flow for mouse users (skip link only visible on focus).
- Fork the repo and create a branch
git checkout -b a11y/navigation-11-skip-link-focus- Implement changes
- Write code in: update
app/layout.js,app/page.js,app/invest/page.js,app/globals.css. - Write comprehensive tests in: create
app/layout.test.tsxβ assert the skip link renders, targets#main-content, and is the first focusable element. - Add documentation: note the skip link in
README.md. - Add comments explaining the focus utility classes.
- Validate a11y with
jest-axeon the layout.
- Write code in: update
- Test and commit
- Run
npm run lint,npm test, andnpm run build. - Cover edge cases: skip link reveals on Tab and moves focus to main.
- Include the full
npm testoutput.
feat: add skip-to-content link and consistent focus-visible styling
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord for questions, reviews, and faster merges: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Fix the globals.css light/dark mismatch and use Geist instead of the hardcoded Arial fallback" labels: type:a11y, area:theming, stack:nextjs, stack:react, stack:typescript, priority:medium, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
Every page sets bg-slate-950 text-slate-100, but app/globals.css declares a white --background/dark --foreground only via prefers-color-scheme, and hard-codes font-family: Arial, Helvetica, sans-serif on body β overriding the Geist font loaded in app/layout.js. This causes a flash of wrong background and the wrong typeface. This issue aligns the global theme tokens with the dark UI and the Geist font.
- Repository scope: Liquifact/Liquifact-frontend only.
- Set the base
bodybackground/foreground to the slate-950/slate-100 palette the pages assume, removing the white-by-default:root. - Replace the
Arial, Helveticafont-familywithvar(--font-geist-sans)so the loaded font is actually applied. - Expose the brand cyan and slate values as theme tokens in the
@themeblock (matching the README design-token section) so they are not scattered as literals. - Verify text/background contrast meets WCAG AA for body and muted (
text-slate-400/500) text.
- Fork the repo and create a branch
git checkout -b a11y/theming-12-global-color-font-fix- Implement changes
- Write code in: update
app/globals.css. - Write comprehensive tests in: create
app/globals.contrast.test.tsxor document a manual contrast audit; add ajest-axesmoke test on the layout. - Add documentation: reconcile the README "Design Tokens" section with the actual tokens.
- Add comments mapping tokens to their hex values.
- Validate a11y: confirm contrast ratios for primary and muted text.
- Write code in: update
- Test and commit
- Run
npm run lint,npm test, andnpm run build. - Cover edge cases: light and dark
prefers-color-scheme. - Include the full
npm testoutput and the contrast-ratio table.
fix: align global theme tokens and apply geist font in globals.css
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord for questions, reviews, and faster merges: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Give disabled marketplace filter buttons accessible 'coming soon' semantics" labels: type:a11y, area:invest, stack:nextjs, stack:react, stack:typescript, priority:medium, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
The filter controls in app/invest/page.js are disabled buttons; disabled elements are removed from the tab order and many screen readers do not announce them, so the visible "Soon" badges convey no information to assistive tech. Until the filters are implemented, this issue makes their unavailable state perceivable and announced. (Supersede when the filters are enabled.)
- Repository scope: Liquifact/Liquifact-frontend only.
- Associate each "Soon" badge with its control programmatically (e.g.
aria-describedby) so the status is announced, not just visually shown. - Prefer
aria-disabled="true"with a no-op handler over the nativedisabledattribute where keeping the control discoverable is desired, or wrap the group in a labelledfieldsetexplaining it is a preview. - Ensure the disabled visual state (opacity 60) still meets contrast for the label text.
- Keep behaviour consistent across all five controls and the Clear Filters button.
- Fork the repo and create a branch
git checkout -b a11y/invest-13-coming-soon-semantics- Implement changes
- Write code in: update
app/invest/page.js(or the extracted filter component if present). - Write comprehensive tests in: create
app/invest/filters.a11y.test.tsxusingjest-axeand role queries. - Add documentation: update
FILTER_CONTRACTS.mdaccessibility section. - Add comments explaining the chosen ARIA approach.
- Validate a11y: no
jest-axeviolations and the "coming soon" status is in the accessibility tree.
- Write code in: update
- Test and commit
- Run
npm run lint,npm test, andnpm run build. - Cover edge cases: keyboard traversal and screen-reader name/description.
- Include the full
npm testoutput.
fix: add accessible coming-soon semantics to disabled marketplace filters
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord for questions, reviews, and faster merges: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Reduce motion for spinners and pulse skeletons under prefers-reduced-motion" labels: type:a11y, area:loading-states, stack:nextjs, stack:react, stack:typescript, priority:low, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
The app uses animate-spin spinners in components/UploadZone.jsx and components/WalletStatus.jsx and animate-pulse skeletons in components/InvoiceListSkeleton.jsx, app/invest/loading.js, and app/invoices/loading.js, with no prefers-reduced-motion handling. Users who request reduced motion still get continuous animation. This issue honours that preference globally.
- Repository scope: Liquifact/Liquifact-frontend only.
- Add a
@media (prefers-reduced-motion: reduce)rule inapp/globals.cssthat disables or minimizesanimate-spin/animate-pulseand other transitions. - Ensure loading state remains perceivable without motion (skeletons still visible; spinners replaced with a static indicator if needed).
- Do not change default (motion-allowed) behaviour.
- Keep
aria-busy/role="status"semantics intact so non-visual users are unaffected.
- Fork the repo and create a branch
git checkout -b a11y/loading-states-14-reduced-motion- Implement changes
- Write code in: update
app/globals.css. - Write comprehensive tests in: create
app/globals.reduced-motion.test.tsxor a documented manual matrix; add ajest-axesmoke check on a loading view. - Add documentation: note reduced-motion support in
README.md. - Add comments on the media query intent.
- Validate a11y: confirm content remains understandable with motion off.
- Write code in: update
- Test and commit
- Run
npm run lint,npm test, andnpm run build. - Cover edge cases: reduced-motion on/off and each animated component.
- Include the full
npm testoutput.
fix: honor prefers-reduced-motion for spinners and skeletons
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord for questions, reviews, and faster merges: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Add a semantic heading hierarchy and main landmark to the home page" labels: type:a11y, area:home, stack:nextjs, stack:react, stack:typescript, priority:low, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
On app/page.js the brand "LiquiFact" in the header is a plain <span>, the two call-to-action cards are <a> blocks wrapping <h2>s, and "API status" is also an <h2> β so the heading outline and the absence of a navigation landmark can confuse screen-reader users. This issue tidies the home page semantics without changing the visual design.
- Repository scope: Liquifact/Liquifact-frontend only.
- Ensure a single, sensible
h1βh2outline; the "API status" panel should not compete with the primary CTA headings (consider a non-heading label or correct level). - Wrap header brand/actions in appropriate landmarks (
<header>/<nav>) with accessible names. - Give the two CTA cards descriptive accessible names so "For Businesses / For Investors" links are unambiguous out of context.
- Keep the existing Tailwind classes and layout intact.
- Fork the repo and create a branch
git checkout -b a11y/home-15-heading-landmarks- Implement changes
- Write code in: update
app/page.js; add copy toapp/copy/en.jsif labels are needed. - Write comprehensive tests in: create
app/page.a11y.test.tsxusingjest-axeand heading-order queries. - Add documentation: note the home page structure in
README.md. - Add comments where heading levels change.
- Validate a11y: no
jest-axeviolations and a logical heading order.
- Write code in: update
- Test and commit
- Run
npm run lint,npm test, andnpm run build. - Cover edge cases: heading order and landmark uniqueness.
- Include the full
npm testoutput.
fix: improve home page heading hierarchy and landmarks
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord for questions, reviews, and faster merges: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Add unit tests for the ToastProvider auto-dismiss, pause/resume, and context guard" labels: type:test, area:toast, stack:nextjs, stack:react, stack:typescript, priority:high, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
components/ToastProvider.jsx implements timed auto-dismiss (AUTO_DISMISS_MS), hover pause/resume via pauseToast/resumeToast, manual dismissal, and a useToast hook that throws when used outside the provider β yet it has zero unit tests. This timer-heavy logic is high-risk for regressions. This issue adds full coverage with fake timers.
- Repository scope: Liquifact/Liquifact-frontend only.
- Test that
success/error/infoenqueue toasts with correct variant styling and default titles fromVARIANT_STYLES. - Test auto-dismiss after
AUTO_DISMISS_MSusing Jest fake timers, plus pause onmouseenterand resume onmouseleave. - Test manual "Close" removal and that
useToastthrows "must be used within a ToastProvider" when unwrapped. - Verify the live region
role="status"/aria-live="polite"wrapper exists and cleanup clears timers on unmount.
- Fork the repo and create a branch
git checkout -b test/toast-16-toastprovider-coverage- Implement changes
- Write code in: no source change expected; if a non-test bug is found, fix it in
components/ToastProvider.jsx. - Write comprehensive tests in: create
components/ToastProvider.test.tsxwith@testing-library/react,user-event, and fake timers. - Add documentation: note testing approach in
README.mdif a testing section is added. - Add comments clarifying timer manipulation.
- Validate a11y with a
jest-axecheck on a rendered toast.
- Write code in: no source change expected; if a non-test bug is found, fix it in
- Test and commit
- Run
npm run lint,npm test, andnpm run build. - Cover edge cases: rapid enqueue, hover during dismiss, and unmount mid-timer.
- Include the full
npm testoutput with coverage for ToastProvider.
test: cover toastprovider auto-dismiss, pause/resume, and hook guard
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord for questions, reviews, and faster merges: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Add behavioral tests for the WalletStatus state machine and toast side effects" labels: type:test, area:wallet, stack:nextjs, stack:react, stack:typescript, priority:high, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
components/WalletStatus.jsx has only an a11y smoke test in components/__tests__/WalletStatus.a11y.test.jsx; none of its six WALLET_STATES, the random-outcome connect simulation, the button label/variant logic, or the toast calls are behaviorally tested. This issue adds deterministic tests by controlling the timer and the random branch.
- Repository scope: Liquifact/Liquifact-frontend only.
- Use Jest fake timers and a mocked
Math.randomto drivesuccess,error, andwrong_networkoutcomes deterministically. - Assert button text/variant, helper text, status-dot class, and the
sr-onlystatus announcement for each state. - Assert connect/disconnect transitions and that the
NO_WALLET"Install Wallet" branch opens the Stellar wallets URL (mockwindow.open). - Verify toast side effects by rendering within a real
ToastProvider.
- Fork the repo and create a branch
git checkout -b test/wallet-17-walletstatus-state-machine- Implement changes
- Write code in: no source change expected unless a bug is found in
components/WalletStatus.jsx. - Write comprehensive tests in: create
components/WalletStatus.test.tsx. - Add documentation: update
WALLET_INTEGRATION_CONTRACT.mdtesting-requirements checklist. - Add comments explaining
Math.random/timer mocking. - Validate a11y: keep the existing axe assertion green.
- Write code in: no source change expected unless a bug is found in
- Test and commit
- Run
npm run lint,npm test, andnpm run build. - Cover edge cases: all six states, rapid connect/disconnect, and external link branch.
- Include the full
npm testoutput with WalletStatus coverage.
test: cover walletstatus state machine and toast side effects
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord for questions, reviews, and faster merges: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Add unit tests for the home page API health check rendering" labels: type:test, area:home, stack:nextjs, stack:react, stack:typescript, priority:medium, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
app/page.js has no unit test. The checkApi handler toggles a loading label, renders the health JSON in a <pre>, and catches network errors into { status: 'error', message } β all untested. This issue adds coverage with a mocked fetch.
- Repository scope: Liquifact/Liquifact-frontend only.
- Mock
global.fetchto return a healthy payload and assert the JSON renders and the button label returns from "Checkingβ¦" to its idle state. - Mock a rejected fetch and assert the error object renders with the thrown message.
- Assert the button is disabled while
loadingis true. - Use
@testing-library/user-eventfor the click andfindBy*queries for async resolution.
- Fork the repo and create a branch
git checkout -b test/home-18-health-check-tests- Implement changes
- Write code in: no source change unless a bug is found in
app/page.js. - Write comprehensive tests in: create
app/page.test.tsx. - Add documentation: note coverage expectations in
README.md. - Add comments documenting fetch mocking.
- Validate a11y: optional
jest-axesmoke check on the page.
- Write code in: no source change unless a bug is found in
- Test and commit
- Run
npm run lint,npm test, andnpm run build. - Cover edge cases: success, network error, and loading-disabled state.
- Include the full
npm testoutput.
test: cover home page api health check rendering
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord for questions, reviews, and faster merges: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Add a Playwright end-to-end test for the Invest marketplace load and empty states" labels: type:test, area:invest, stack:nextjs, stack:react, stack:typescript, priority:medium, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
The only Playwright spec is tests/toast.spec.jsx for the upload toast; the Invest marketplace in app/invest/page.js β with its skeleton-to-list transition and polite aria-live announcement β has no e2e coverage. This issue adds a marketplace e2e spec using the existing Playwright config.
- Repository scope: Liquifact/Liquifact-frontend only.
- Navigate to
/invest, wait for the skeleton (aria-busy/aria-label "Loading investable invoices") to resolve, and assert the three mock invoices render with issuer/amount/yield/maturity. - Assert the polite status region announces "3 investable invoices loaded".
- Cover the empty state by stubbing the loader/route to return no invoices and asserting
copy.invest.emptyState. - Reuse the
baseURLandwebServersettings inplaywright.config.mjs; keep specs undertests/so Jest continues to ignore them.
- Fork the repo and create a branch
git checkout -b test/invest-19-marketplace-e2e- Implement changes
- Write code in: test-only.
- Write comprehensive tests in: create
tests/invest.spec.jsx. - Add documentation: add the new e2e spec to the README test section.
- Add comments on any route stubbing used.
- Validate a11y: optionally assert the status region is present.
- Test and commit
- Run
npm run lintandnpm run test:e2e. - Cover edge cases: loaded list and empty marketplace.
- Include the Playwright run output (and trace on first retry per config).
test: add playwright e2e for invest marketplace load and empty states
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord for questions, reviews, and faster merges: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Expand UploadZone tests to cover drag-and-drop, keyboard activation, and double-submit" labels: type:test, area:upload, stack:nextjs, stack:react, stack:typescript, priority:medium, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
components/UploadZone.test.jsx covers basic file validation but not the drag-and-drop handlers (handleDrop/onDragOver/onDragLeave), the keyboard activation (Enter/Space triggers the hidden input), or the submit state machine's double-submit guard (status !== 'idle'). This issue closes those gaps.
- Repository scope: Liquifact/Liquifact-frontend only.
- Simulate drag-over (border state changes), drop with a valid PDF, and drop with an invalid type, asserting the
role="alert"message. - Simulate
EnterandSpaceon the dropzonerole="button"and assert it clicks the hidden#invoice-file-input. - Use fake timers to walk
uploading β tokenizing β successand assert the disabled/aria-disabledbutton cannot submit twice. - Assert each
role="status"transition copy matches the strings consumed by the e2e spec.
- Fork the repo and create a branch
git checkout -b test/upload-20-dragdrop-keyboard-coverage- Implement changes
- Write code in: test-only unless a bug surfaces in
components/UploadZone.jsx. - Write comprehensive tests in: extend
components/UploadZone.test.jsxor addcomponents/UploadZone.interactions.test.tsx. - Add documentation: none required beyond test comments.
- Add comments explaining DataTransfer mocking.
- Validate a11y: keep an axe check on the rendered form.
- Write code in: test-only unless a bug surfaces in
- Test and commit
- Run
npm run lint,npm test, andnpm run build. - Cover edge cases: invalid drop, oversized drop, keyboard activation, and double-submit.
- Include the full
npm testoutput with UploadZone coverage.
test: cover uploadzone drag-and-drop, keyboard, and double-submit
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord for questions, reviews, and faster merges: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Add Content-Security-Policy and security response headers via next.config and middleware" labels: type:security, area:headers, stack:nextjs, stack:react, stack:typescript, priority:high, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
next.config.mjs is an empty config with no headers() function, so the app ships without a Content-Security-Policy, X-Content-Type-Options, Referrer-Policy, or frame protection. Before wallet and API integration handle financial data, the app needs baseline header hardening. This issue adds security headers and a CSP.
- Repository scope: Liquifact/Liquifact-frontend only.
- Add an async
headers()tonext.config.mjssettingX-Content-Type-Options: nosniff,Referrer-Policy: strict-origin-when-cross-origin,X-Frame-Options: DENY(or CSPframe-ancestors), and aPermissions-Policy. - Define a CSP that allows the app's own origin, the
NEXT_PUBLIC_API_URLforconnect-src, and Google Fonts used by Geist; document any required'unsafe-inline'for styles with justification. - Avoid breaking the
fetchcalls to the backend or font loading. - Keep the config compatible with Next.js 16 App Router.
- Fork the repo and create a branch
git checkout -b security/headers-21-csp-and-headers- Implement changes
- Write code in: update
next.config.mjs(optionally addmiddleware.jsfor per-request nonces). - Write comprehensive tests in: create
security/headers.test.tsxasserting the headers config shape, or a documented runtime check vianpm run build && npm run start. - Add documentation: document the CSP and
connect-srcallowance inREADME.md. - Add comments justifying each directive.
- Validate security: confirm no console CSP violations on each page.
- Write code in: update
- Test and commit
- Run
npm run lint,npm test, andnpm run build. - Cover edge cases: API origin allowed, fonts load, and framing blocked.
- Include the response-header output and a short threat-model note.
feat: add content-security-policy and security response headers
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord for questions, reviews, and faster merges: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Validate and sanitize NEXT_PUBLIC_API_URL before issuing requests" labels: type:security, area:config, stack:nextjs, stack:react, stack:typescript, priority:medium, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
NEXT_PUBLIC_API_URL is read inline in app/page.js (and documented in .env.local.example) and concatenated directly into a fetch URL with no validation, so a misconfigured or malicious value (e.g. a javascript: or unexpected origin) flows straight into requests. This issue centralizes and validates the env config.
- Repository scope: Liquifact/Liquifact-frontend only.
- Create
lib/config/env.jsthat parsesNEXT_PUBLIC_API_URL, enforceshttp/httpsand a well-formed origin (vianew URL(...)), and exports a frozen config object with thehttp://localhost:3001default. - Throw a clear, early error in development when the value is invalid; never silently fall back in a way that masks misconfiguration.
- Replace the inline
process.env.NEXT_PUBLIC_API_URL || '...'reads across the codebase with this helper. - Document the optional
NEXT_PUBLIC_STELLAR_NETWORKvalue validation too.
- Fork the repo and create a branch
git checkout -b security/config-22-validate-api-url- Implement changes
- Write code in: create
lib/config/env.js; updateapp/page.jsand any other consumers. - Write comprehensive tests in: create
lib/config/env.test.tsxβ valid, missing, non-URL, and disallowed-scheme cases. - Add documentation: expand the env section in
README.mdand.env.local.example. - Add JSDoc on the exported config.
- Validate security: reject non-http(s) schemes and log a safe error.
- Write code in: create
- Test and commit
- Run
npm run lint,npm test, andnpm run build. - Cover edge cases: empty, malformed, trailing-slash, and disallowed scheme.
- Include the full
npm testoutput and a note on the validation rules.
feat: validate and centralize NEXT_PUBLIC_API_URL configuration
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord for questions, reviews, and faster merges: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Enforce client-side PDF content validation and safe filename handling in UploadZone" labels: type:security, area:upload, stack:nextjs, stack:react, stack:typescript, priority:medium, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
components/UploadZone.jsx validates only f.type === 'application/pdf' and f.size, but the browser-reported MIME type is spoofable and the raw file.name is rendered into the DOM. For a financial document upload, content-based checks and safe filename handling reduce the risk of malicious or mislabelled files. This issue strengthens validation.
- Repository scope: Liquifact/Liquifact-frontend only.
- Verify the PDF magic bytes (
%PDF-) by reading the first bytes of the file in addition to the MIME/extension check. - Sanitize/escape
file.namebefore display and cap its rendered length to avoid layout/clipboard abuse. - Keep the existing
FILE_CONSTRAINTS(size, single file) and the accessiblerole="alert"error messaging. - Reject zero-byte files and files whose extension and detected content disagree.
- Fork the repo and create a branch
git checkout -b security/upload-23-pdf-content-validation- Implement changes
- Write code in: update
components/UploadZone.jsx; optionally extract alib/validation/pdf.js. - Write comprehensive tests in: extend
components/UploadZone.test.jsxand createlib/validation/pdf.test.tsxβ valid PDF bytes, spoofed MIME, zero-byte, and long filename. - Add documentation: note the validation rules in
README.md. - Add JSDoc on the validation helper.
- Validate security: never execute or trust file content; only inspect bytes.
- Write code in: update
- Test and commit
- Run
npm run lint,npm test, andnpm run build. - Cover edge cases: spoofed
.pdf, empty file, and oversized name. - Include the full
npm testoutput and a short threat note.
feat: validate pdf magic bytes and sanitize filenames in uploadzone
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord for questions, reviews, and faster merges: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Add automated dependency and secret scanning to the CI workflow" labels: type:security, area:ci, stack:nextjs, stack:react, stack:typescript, priority:medium, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
.github/workflows/ci.yml runs only lint and npm test; there is no npm audit, no dependency review, and no secret scan. As wallet/API integration adds dependencies and handles financial flows, the pipeline should catch vulnerable packages and leaked secrets. This issue adds those gates.
- Repository scope: Liquifact/Liquifact-frontend only.
- Add an
npm audit --audit-level=highstep (oractions/dependency-review-actionon PRs) that fails on high/critical advisories. - Add a secret-scan step (e.g. gitleaks) over the diff.
- Keep the existing lint and test jobs; run new checks in parallel where possible to keep CI fast.
- Document how to triage and waive a false-positive advisory.
- Fork the repo and create a branch
git checkout -b security/ci-24-audit-and-secret-scan- Implement changes
- Write code in: update
.github/workflows/ci.yml; optionally add a gitleaks config. - Write comprehensive tests in: validate by triggering CI on the PR; add a documented local
npm auditrun. - Add documentation: add a "Security in CI" subsection to
README.md. - Add comments in the workflow explaining each gate.
- Validate security: ensure scans run on pull_request from forks safely.
- Write code in: update
- Test and commit
- Run
npm run lint,npm test,npm run build, andnpm auditlocally. - Cover edge cases: clean repo passes; an injected high advisory fails.
- Include the CI run link/output and triage notes.
ci: add dependency audit and secret scanning to the workflow
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord for questions, reviews, and faster merges: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Document the lib/api data-fetching contract and frontend-backend integration" labels: type:docs, area:api, stack:nextjs, stack:react, stack:typescript, priority:medium, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
The README mentions the backend Express API and NEXT_PUBLIC_API_URL, but the only real network call is the inline health check in app/page.js, and the invoice data is mocked in app/invest/page.js. There is no document describing the expected endpoints, response shapes, or error conventions for the frontend. This issue creates that contract doc.
- Repository scope: Liquifact/Liquifact-frontend only.
- Create
docs/api-integration.mddescribing the endpoints the frontend expects (/health,/invoiceslist, invoice detail, upload) with request/response examples matching the existing mock item contract{ id, issuer, amount, currency, dueDate, yield, status }. - Document error-response conventions and how
ErrorBanner/ToastProvidershould surface them. - Reference the existing
FILTER_CONTRACTS.mdquery-param contract and theNEXT_PUBLIC_API_URLbase. - Keep it accurate to today's mocked state and clearly mark what is "planned".
- Fork the repo and create a branch
git checkout -b docs/api-25-integration-contract- Implement changes
- Write code in: docs-only.
- Write comprehensive tests in: not applicable; if example JSON is referenced by tests later, keep it copy-pasteable.
- Add documentation: create
docs/api-integration.mdand link it fromREADME.md. - Add a versioned changelog note for the contract.
- Validate accuracy against the current code paths.
- Test and commit
- Run
npm run lintandnpm run buildto confirm docs links/format do not break anything. - Cover edge cases: ensure example payloads match the rendered fields.
- Include a rendered preview of the new doc.
docs: add frontend-backend api integration contract
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord for questions, reviews, and faster merges: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Write a component library reference for the shared UI components" labels: type:docs, area:components, stack:nextjs, stack:react, stack:typescript, priority:low, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
The README "UI Components" section briefly lists Footer, ErrorBanner, InvoiceListSkeleton, and WalletStatus, but the props it describes for ErrorBanner (variant/message) do not match the actual signature in components/ErrorBanner.jsx (variant: "server"|"validation", title, description, details, actionLabel, onAction, previewLabel). This issue produces an accurate component reference and adds the missing components.
- Repository scope: Liquifact/Liquifact-frontend only.
- Document every component under
components/:ErrorBanner,Footer,InvoiceListSkeleton,ToastProvider/useToast,UploadZone(and exportedFILE_CONSTRAINTS/Spinner), andWalletStatus(andWALLET_STATES). - Correct the inaccurate ErrorBanner props in
README.md. - For each: purpose, props/exports with types, accessibility notes, and a minimal usage example.
- Note which components are client (
'use client') vs server components.
- Fork the repo and create a branch
git checkout -b docs/components-26-component-reference- Implement changes
- Write code in: docs-only; optionally add JSDoc to the components to keep docs in sync.
- Write comprehensive tests in: not applicable.
- Add documentation: create
docs/components.mdand fix theREADME.mdUI section. - Add usage snippets that compile against the real signatures.
- Validate accuracy by cross-checking each prop against source.
- Test and commit
- Run
npm run lintandnpm run build. - Cover edge cases: every exported symbol is documented.
- Include a rendered preview of the new doc.
docs: add accurate shared component library reference
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord for questions, reviews, and faster merges: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Add a testing guide covering Jest unit tests and Playwright e2e setup" labels: type:docs, area:testing, stack:nextjs, stack:react, stack:typescript, priority:low, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
The repo has a real testing setup β Jest with next/jest in jest.config.js, jest-axe wired in jest.setup.js, and Playwright in playwright.config.mjs β but no doc explains how to run, structure, or extend tests, including the important detail that Playwright specs under tests/ are excluded from Jest. This issue writes that guide.
- Repository scope: Liquifact/Liquifact-frontend only.
- Explain
npm test(Jest, jsdom) vsnpm run test:e2e(Playwright), the@/module alias mapping, and thetestPathIgnorePatternsexclusion oftests/. - Document the
jest-axeaccessibility-assertion pattern used incomponents/__tests__/ErrorBanner.a11y.test.jsx. - Document file-naming conventions (
*.test.jsx/*.test.tsxco-located vs__tests__/, and*.spec.jsxfor e2e undertests/). - Note the CI step in
.github/workflows/ci.ymlthat runs tests.
- Fork the repo and create a branch
git checkout -b docs/testing-27-testing-guide- Implement changes
- Write code in: docs-only.
- Write comprehensive tests in: not applicable; ensure example snippets are runnable.
- Add documentation: create
docs/testing.mdand link fromREADME.md. - Add a troubleshooting subsection (e.g. fake timers, axe matchers).
- Validate by following the guide on a clean checkout.
- Test and commit
- Run
npm testandnpm run test:e2eto confirm the documented commands work. - Cover edge cases: ensure the alias and ignore-pattern notes are correct.
- Include the command outputs referenced in the doc.
docs: add jest and playwright testing guide
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord for questions, reviews, and faster merges: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Add CONTRIBUTING, issue, and pull request templates for the campaign" labels: type:docs, area:community, stack:nextjs, stack:react, stack:typescript, priority:low, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
Contribution guidance currently lives only as a section inside README.md; there is no CONTRIBUTING.md, and .github/ contains only .github/workflows/ci.yml β no issue or PR templates. For an open-source bounty campaign this makes onboarding and PR consistency harder. This issue adds the standard community files.
- Repository scope: Liquifact/Liquifact-frontend only.
- Create
CONTRIBUTING.mdcapturing the fork β branch βnpm ciβ lint/test/build β PR flow already described in the README, plus the conventional-commit style. - Create
.github/PULL_REQUEST_TEMPLATE.mdwith a checklist (lint/test/build pass, coverage, a11y, docs updated). - Create
.github/ISSUE_TEMPLATE/with a bug report and feature request template. - Reference the Discord community and the campaign labels.
- Fork the repo and create a branch
git checkout -b docs/community-28-contributing-templates- Implement changes
- Write code in: docs-only.
- Write comprehensive tests in: not applicable.
- Add documentation: create
CONTRIBUTING.md,.github/PULL_REQUEST_TEMPLATE.md, and.github/ISSUE_TEMPLATE/files; link fromREADME.md. - Keep checklists aligned with the CI gates.
- Validate that template front-matter renders on GitHub.
- Test and commit
- Run
npm run lintandnpm run build. - Cover edge cases: templates render correctly and links resolve.
- Include a rendered preview of the templates.
docs: add contributing guide and issue/pr templates
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord for questions, reviews, and faster merges: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Extract a shared invoice card and type so the marketplace and skeleton stay in sync" labels: type:refactor, area:invest, stack:nextjs, stack:react, stack:typescript, priority:medium, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
The invoice card markup is duplicated as inline JSX in the marketplace list in app/invest/page.js and mirrored structurally by the placeholder rows in components/InvoiceListSkeleton.jsx, with the { id, issuer, amount, currency, dueDate, yield, status } shape redefined in comments in both files. They can drift apart. This issue extracts a single InvoiceCard and a shared invoice type/shape.
- Repository scope: Liquifact/Liquifact-frontend only.
- Create
components/InvoiceCard.jsxrendering one invoice (issuer, status badge, amount/currency, yield, maturity) and use it inInvestMarketplace. - Define the invoice shape once in
lib/types/invoice.js(JSDoc typedef) and reference it from the card, the skeleton, and the API client. - Keep the skeleton's column widths visually matched to the real card.
- No behavioural/visual change to the rendered marketplace.
- Fork the repo and create a branch
git checkout -b refactor/invest-29-shared-invoice-card- Implement changes
- Write code in: create
components/InvoiceCard.jsxandlib/types/invoice.js; updateapp/invest/page.jsandcomponents/InvoiceListSkeleton.jsx. - Write comprehensive tests in: create
components/InvoiceCard.test.tsx; keepcomponents/InvoiceListSkeleton.test.jsxgreen. - Add documentation: document
InvoiceCardin the README UI section. - Add a JSDoc typedef for the invoice shape.
- Validate a11y: card keeps an accessible status label.
- Write code in: create
- Test and commit
- Run
npm run lint,npm test, andnpm run build. - Cover edge cases: missing optional fields and long issuer names.
- Include the full
npm testoutput and a before/after note confirming no visual change.
refactor: extract shared invoicecard and invoice type
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord for questions, reviews, and faster merges: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward. ++++++
type: Feature title: "Add OpenGraph/Twitter metadata and a generated icon set to the root layout" labels: type:enhancement, area:seo, stack:nextjs, stack:react, stack:typescript, priority:low, MAYBE REWARDED, GRANTFOX OSS, OFFICIAL CAMPAIGN assignees: ''
The root app/layout.js exports only title and description in its metadata; there are no OpenGraph or Twitter card fields, no metadataBase, and no app icons beyond the default app/favicon.ico. Links to LiquiFact shared on social or chat render without a preview image or proper title. This issue completes the metadata for a polished, shareable site.
- Repository scope: Liquifact/Liquifact-frontend only.
- Extend the
metadataexport withmetadataBase,openGraph(title, description, url, siteName, image), andtwittercard fields, reusing copy fromapp/copy/en.jswhere sensible. - Add an OG image (static asset under
public/or anapp/opengraph-imageroute) consistent with the slate/cyan brand. - Add
app/icon/ apple-touch icon as supported by the App Router metadata API. - Keep the existing Geist font setup and
lang="en"on<html>.
- Fork the repo and create a branch
git checkout -b enhancement/seo-30-social-metadata-icons- Implement changes
- Write code in: update
app/layout.js; add OG image/icon assets underpublic/orapp/. - Write comprehensive tests in: create
app/layout.metadata.test.tsxasserting the exported metadata fields. - Add documentation: note the social metadata in
README.md. - Add comments mapping metadata fields to their source copy.
- Validate: confirm the OG image resolves and the build emits the icons.
- Write code in: update
- Test and commit
- Run
npm run lint,npm test, andnpm run build. - Cover edge cases: absolute
metadataBaseURL and image dimensions. - Include the full
npm testoutput and a screenshot of the social preview.
feat: add opengraph/twitter metadata and app icons to root layout
- Minimum 95 percent test coverage for impacted modules.
- Clear, reviewer-focused documentation.
- Timeframe: 96 hours.
- π¬ Join the Liquifact community on Discord for questions, reviews, and faster merges: https://discord.gg/JrGPH4V3
- β This is a GrantFox OSS / Official Campaign task and may be rewarded. When your PR is merged you'll be prompted to rate the project β if this issue and the maintainers helped you ship, we'd be grateful for a 5-star rating. Clear questions in Discord and tidy, well-tested PRs are the fastest path to a merge and a reward.