Skip to content

Static Web Form for Consortia Invite Links #114

@kalitopix

Description

@kalitopix

Overview

Create a standalone static web page that allows users to join consortia via invite links without requiring the desktop app. The form should display invite information, provide embedded login/signup functionality, automatically join users to the consortium after authentication, and include a link to download the app.

Requirements

1. Project Setup

  • Create new static site project (e.g., invite-site/ directory in the api)
  • Set up build/deployment pipeline
  • Configure hosting at /invite/{token} at the same endpoint the api is served at
  • Ensure GraphQL API endpoint is accessible from browser (CORS configured)

2. Public Invite Info Query

  • Implement getInviteInfo GraphQL query call
    • Extract inviteToken from URL parameter
    • Query: getInviteInfo(inviteToken: String!)
    • Returns: consortiumName, leaderName, isValid, isExpired
  • Display invite message: "{leaderName} invites you to join {consortiumName} on NeuroFLAME"
  • Handle loading state while fetching invite info
  • Show error if token is expired or invalid

3. Embedded Login Form

  • Create login form component
    • Username input field
    • Password input field
    • "Log In" button
  • Implement login mutation call
    • Mutation: login(username: String!, password: String!)
    • Store accessToken in localStorage or sessionStorage
    • Handle authentication errors (invalid credentials)
  • Show loading state during login
  • Display error messages for failed login attempts

4. Embedded Signup Form

  • Create signup form component
    • Username input field
    • Password input field
    • "Sign Up" button
  • Implement userCreate mutation call
    • Mutation: userCreate(username: String!, password: String!)
    • Returns LoginOutput with access token
    • Store accessToken in localStorage or sessionStorage
  • Auto-login after successful signup
  • Show loading state during signup
  • Display error messages for failed signup (e.g., username already exists)

5. Auto-Join Functionality

  • After successful login/signup:
    • Extract inviteToken from URL
    • Call consortiumJoin mutation with inviteToken
    • Mutation: consortiumJoin(inviteToken: String!)
  • Handle join success:
    • Show success message: "You've been added to {consortiumName}!"
    • Display next steps (download app, etc.)
  • Handle join errors:
    • Already a member: "You're already a member of this consortium."
    • Expired token: "This invite link has expired. Please contact {leaderName} for a new invite."
    • Invalid token: "Invalid invite link."
  • Show loading state during join process

6. App Download Link

  • Add prominent download link section
  • Link to latest release/download page
    • Could be GitHub releases, app store, or dedicated download page
  • Text: "Download NeuroFLAME to get started" or similar
  • Display link after successful join or as persistent element

7. Error Handling

  • Expired token:
    • Message: "This invite link has expired. Please contact {leaderName} for a new invite."
    • Disable login/signup forms
  • Invalid token:
    • Message: "Invalid invite link."
    • Disable login/signup forms
  • Already a member:
    • Message: "You're already a member of this consortium."
    • Show download link
  • Network errors:
    • Display user-friendly error messages
    • Provide retry option

8. UI/UX Requirements

  • Clean, simple, professional design
  • Mobile-responsive layout
  • Clear visual hierarchy
  • Prominent call-to-action buttons
  • Loading states for all async operations
  • Smooth transitions between states
  • Accessible (keyboard navigation, screen reader support)
  • Branding consistent with NeuroFLAME

9. Technical Implementation

  • Choose framework/stack (vanilla HTML/JS, React, Vue, etc.)
  • Set up GraphQL client (Apollo Client, urql, or fetch)
  • Configure API endpoint URL
  • Handle token storage (localStorage/sessionStorage)
  • Implement routing for invite token parameter
  • Set up build process (if using framework)
  • Configure deployment (Netlify, Vercel, GitHub Pages, etc.)

10. Testing

  • Test invite info display with valid token
  • Test invite info display with expired token
  • Test invite info display with invalid token
  • Test login flow: valid credentials → auto-join
  • Test login flow: invalid credentials → error message
  • Test signup flow: new user → auto-login → auto-join
  • Test signup flow: existing username → error message
  • Test auto-join after successful auth
  • Test error handling for already-a-member case
  • Test mobile responsiveness
  • Test on different browsers (Chrome, Firefox, Safari, Edge)
  • Test accessibility (keyboard navigation, screen readers)

User Flow

  1. User clicks invite link → https://neuroflame.org/invite/{token}
  2. Page loads → fetches invite info via getInviteInfo query
  3. Displays: "{LeaderName} invites you to join {ConsortiumName} on NeuroFLAME"
  4. User sees login/signup forms
  5. User signs up or logs in
  6. After successful auth → automatically calls consortiumJoin with token
  7. Success message: "You've been added to {ConsortiumName}!"
  8. Download link displayed: "Download NeuroFLAME to get started"

Technical Notes

GraphQL Queries/Mutations Needed

# Query (public, no auth required)
query GetInviteInfo($inviteToken: String!) {
  getInviteInfo(inviteToken: $inviteToken) {
    consortiumName
    leaderName
    isValid
    isExpired
  }
}

# Mutations (require auth after login/signup)
mutation Login($username: String!, $password: String!) {
  login(username: $username, password: $password) {
    accessToken
    userId
    username
  }
}

mutation UserCreate($username: String!, $password: String!) {
  userCreate(username: $username, password: $password) {
    accessToken
    userId
    username
  }
}

mutation ConsortiumJoin($inviteToken: String!) {
  consortiumJoin(inviteToken: $inviteToken)
}

Token Storage

  • Store accessToken from login/signup responses
  • Use for authenticated GraphQL requests
  • Can use localStorage or sessionStorage
  • Include in GraphQL request headers: x-access-token: {accessToken}

Acceptance Criteria

  • Static web form is accessible without desktop app
  • Invite info displays correctly: "{leader} invites you to join {consortium} on NeuroFLAME"
  • Login form works and stores access token
  • Signup form works and auto-logs in user
  • After auth, user is automatically added to consortium
  • Success message displays after successful join
  • App download link is present and functional
  • Error handling works for expired/invalid tokens
  • Error handling works for already-member case
  • Mobile-responsive design
  • Works across major browsers
  • Zero-friction onboarding: leader emails link → users join without app

Related Backend Requirements

  • getInviteInfo query must be implemented (public, no auth)
  • consortiumJoin mutation must support inviteToken parameter
  • GraphQL API must have CORS configured for static site domain

Metadata

Metadata

Assignees

Labels

No labels
No labels

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions