{"id":"public-portal","type":"module","title":"Public Portal and Intake Funnel","status":"ga","audience":["applicant","org-admin"],"scope":"supplier","tier_min":"free","aliases":["3","apply","intake"],"summary":"A per-org branded public front door for inbound opportunities. An applicant submits by chat or dynamic form without an account and gets a reference number plus a self-serve status page.","keywords":["portal","intake","applicant-chat","form-builder","unauthenticated","branding"],"body":{"what_it_is":"The firm's public, unauthenticated **front door for inbound opportunities**.\nEach firm gets a branded portal at `{firm_slug}.klarum.com` (Next.js\nmiddleware rewrites the subdomain to `/portal/{firm_slug}`). An applicant\nlands on the branded page, submits a project by **chatting with an AI intake\nassistant** or **filling a dynamic form** (the firm picks which), optionally\nattaches documents (RFP/EOI/business plan/financial model), and receives a\nreference number plus a public status page. On the firm side, an admin\nconfigures what the portal collects via a no-code **inbound form builder**.\nThe portal layout is deliberately isolated: no sidebar, no auth guard, no\nsubscription check.\n","what_it_helps_users_do":"- **For the firm:** turn a shareable URL into a structured inbound channel;\n  every submission becomes a normalised `projects` row plus a substrate\n  `opportunities` row, ready for triage. The firm controls branding and field\n  set without engineering.\n- **For the applicant:** submit in under a minute, conversationally or by\n  form, attach the source RFP, get an immediate reference and confirmation\n  email, and self-serve a status check, all without an account.\n- **For the platform:** unify inbound/outbound onto one substrate\n  (`source_type=inbound`) so submissions flow through the same\n  matching/workspace/decision machinery as discovered tenders.\n"},"engines":[],"integrations":[],"capabilities":[{"id":"applicant-chat-intake","type":"capability","title":"Conversational intake assistant","summary":"A stateless slot-filling LLM conversation that collects the submission fields, never re-asks a known field, never invents a value and emits strict JSON at temperature 0.4.","status":"ga","scope":null,"keywords":["chat","slot-filling","stateless"],"body":null},{"id":"inbound-form-schema","type":"capability","title":"One schema, two consumers","summary":"A single builder schema drives both the portal render and the server-side validation, so the form a user sees and the rules the server enforces cannot drift.","status":"ga","scope":null,"keywords":["form-builder","validation","no-drift"],"body":null},{"id":"portal-reference-status","type":"capability","title":"Reference and status check","summary":"A URL-safe INB-XXXXXXXX reference plus the applicant email acts as a bearer pair for the public status page; a mismatch 404s rather than confirming the reference exists.","status":"ga","scope":null,"keywords":["reference","no-enumeration","status"],"body":null},{"id":"portal-rate-limits","type":"capability","title":"Rate limiting on an unauthenticated surface","summary":"60 reads, 10 applies and 30 chat turns per minute, with a stateless chat so a bounced visit costs nothing.","status":"ga","scope":null,"keywords":["rate-limit","abuse","cost"],"body":null}]}