Try it now at upliftapp.online
A real-time web application for facilitating structured appreciation sessions where team members anonymously write and share positive notes with each other.
Uplift is a guided group activity designed to help teams feel seen and appreciated. Participants join a session, write appreciation notes for their teammates, and then take turns reading these anonymous notes aloud. The anonymity encourages genuine appreciation while the group reading creates a shared moment of connection.
- Start or Join: One person creates a new session and shares the session code (or link) with their team
- Lobby: Participants join using the code and wait in the lobby until everyone arrives
- Writing: The host starts the writing phase. Each participant writes appreciation notes for every other participant
- Reading: Once everyone submits their notes, participants take turns drawing and reading random notes aloud
- Completion: When all notes have been read, participants can export their received notes as text or PDF
- Real-time synchronisation: All participants see updates instantly via WebSocket
- Accessible: Full keyboard navigation, screen reader support, and ARIA live regions
- Responsive: Works on desktop, tablet, and mobile devices
- Theme support: Light (Cupcake) and dark (Sunset) themes with system preference detection
- Session management: Host controls, participant removal, automatic host reassignment
- Export options: Download notes as text file or save as PDF via browser print
- Auto-reconnect: Handles network interruptions with exponential backoff
- Inactivity timeout: Sessions automatically timeout after 30 minutes of inactivity
- Alpine.js 3.15.0: Lightweight reactive framework for UI state management
- DaisyUI 5.0.0: Component library built on Tailwind CSS
- Tailwind CSS 4.0: Utility-first CSS framework via Vite plugin
- Vite 7: Fast build tool and development server
The frontend is a single-page application with no routing. State transitions are handled by Alpine.js and all UI updates happen in response to WebSocket messages or user actions.
- Go 1.25.1: HTTP server and WebSocket handler
- Gorilla WebSocket: WebSocket library for real-time bidirectional communication
- Standard library: HTTP server using
net/http
The backend manages session state, coordinates message passing between clients, and handles WebSocket lifecycle events (connect, disconnect, timeout).
The application uses WebSocket for all real-time communication:
- Frontend connects to
/wsendpoint - Messages are JSON with
typeanddatafields - Backend broadcasts state changes to all session participants
- Automatic reconnection with exponential backoff (1s, 2s, 4s, 8s, 16s, max 30s)
- Go 1.25+: Download Go
- Node.js 18+: Download Node.js
- npm: Comes with Node.js
# Install Go dependencies
go mod download
# Install Node.js dependencies
npm installgo build -o uplift ./cmd/serverYou need two terminal windows running simultaneously:
Terminal 1 - Go Backend (port 8080):
./upliftTerminal 2 - Vite Dev Server (port 3000):
npm run devThe Vite dev server proxies WebSocket connections to the Go backend, so you only need to open http://localhost:3000 in your browser.
# Build frontend assets
npm run build
# Build Go binary
go build -o uplift ./cmd/server
# Copy built assets to static directory
cp -r dist/* static/# Set PORT environment variable (optional, defaults to 8080)
export PORT=8080
# Run the server
./upliftThe server will serve static files from ./static and WebSocket connections on /ws.
.
├── cmd/
│ └── server/
│ └── main.go # Application entry point
├── internal/
│ ├── session/
│ │ ├── manager.go # Session lifecycle management
│ │ └── session.go # Session state and business logic
│ └── websocket/
│ ├── client.go # WebSocket client connection handling
│ ├── handler.go # WebSocket HTTP upgrade handler
│ ├── hub.go # Central message router
│ └── messagehandler.go # Message processing and session coordination
├── src/
│ ├── css/
│ │ └── styles.css # Custom styles (animations, print, accessibility)
│ └── js/
│ └── app.js # Alpine.js application logic
├── static/ # Production static files (after build)
├── dist/ # Vite build output (gitignored)
├── index.html # Main HTML entry point
├── main.js # Frontend entry point (imports Alpine, styles)
├── package.json # Node.js dependencies and scripts
├── go.mod # Go module definition
├── go.sum # Go dependency checksums
└── vite.config.js # Vite configuration (Tailwind, proxy, build)
PORT: HTTP server port (default:8080)
-
Build the production assets:
npm run build go build -o uplift ./cmd/server cp -r dist/* static/ -
Deploy the binary and static directory to your hosting platform
-
Ensure the server can accept WebSocket connections (check reverse proxy configuration if using nginx/Apache)
-
Set the
PORTenvironment variable if needed
Heroku:
- Buildpacks required:
heroku/nodejsandheroku/go - Procfile:
web: ./uplift - PORT is automatically set by Heroku
Docker:
FROM golang:1.25-alpine AS builder
WORKDIR /app
COPY . .
RUN go build -o uplift ./cmd/server
FROM node:18-alpine AS frontend
WORKDIR /app
COPY package*.json ./
RUN npm install
COPY . .
RUN npm run build
FROM alpine:latest
WORKDIR /app
COPY --from=builder /app/uplift .
COPY --from=frontend /app/dist ./static
EXPOSE 8080
CMD ["./uplift"]Fly.io:
- Use Go buildpack
- Ensure WebSocket support is enabled
- Set internal port to 8080 in fly.toml
- Chrome/Edge 90+
- Firefox 88+
- Safari 14+
- Mobile browsers (iOS Safari, Chrome Mobile)
Requires JavaScript enabled and WebSocket support.
MIT