A modern web application built with React, TypeScript, and TanStack Router.
- Authentication: better-auth integration with email/password login, password reset, and invitation-based onboarding
- Modern UI: Beautiful, responsive design with Tailwind CSS
- Type Safety: Full TypeScript support
- Routing: TanStack Router for type-safe routing
- Internationalization: i18next for multi-language support
- State Management: Zustand for global state
- Form Validation: Zod for schema validation
- UI Components: Radix UI primitives with custom styling
- Containerized Development: Docker/Podman support for consistent environments
Authentication is powered by better-auth. The browser client lives in src/lib/auth-client.ts and talks to the better-auth server exposed by the Fluent API (configured via VITE_BETTER_AUTH_URL).
- Login (
/login): email and password sign-in. - Password reset (
/reset-password): request a reset email, then set a new password. - Invitation onboarding (
/accept-invitation): new users join by accepting an emailed invitation — there is no self-service signup. - Sessions: read the current session with
authClient.useSession(), or use theuseAuth()hook (src/hooks/useAuth.ts), which exposesuser,isAuthenticated,isLoading,login, andlogout. - Protected routes: pages under the
_authenticatedlayout route are guarded — unauthenticated visitors are redirected to/login?returnTo=<url>, wherereturnTois the full URL they were trying to reach.
-
Create a
.envfile with the required variables. At minimum you must setVITE_API_URL,VITE_ENVIRONMENT,VITE_AQUIFER_API_URL,VITE_AQUIFER_API_KEY,VITE_YOUVERSION_API_URL,VITE_YOUVERSION_API_KEYandVITE_BETTER_AUTH_URL— they are all validated at startup, and missing any of them fails with an "Invalid environment configuration" error. See Environment Configuration for the full list and how to manage per-environment files. To point the app at a better-auth server, set:VITE_BETTER_AUTH_URL=http://localhost:9999/api/auth
-
Start the development server:
pnpm dev
-
Visit
/loginto sign in.
- Node.js 24.13.x
- pnpm
pnpm installpnpm devpnpm buildpnpm lint
pnpm lint:fixpnpm typechecksrc/
├── components/ # Reusable UI components
│ ├── auth/ # Authentication components
│ └── ui/ # Base UI components
├── hooks/ # Custom React hooks
├── layouts/ # Page layouts
├── lib/ # Utility libraries
├── routes/ # Route definitions
├── store/ # Global state management
└── app.tsx # Main app component
- React 18 - UI framework
- TypeScript - Type safety
- TanStack Router - Type-safe routing
- Tailwind CSS - Styling
- better-auth - Authentication
- Zustand - State management
- Zod - Schema validation
- i18next - Internationalization
- Vite - Build tool
- Docker/Podman - Containerized development
- ESLint - Code linting
- Prettier - Code formatting
Before you begin, ensure you have the following installed:
- Node.js: This project requires Node.js version 24.13.x
- We recommend using nvm (Node Version Manager) to manage Node.js versions
- pnpm: This project uses pnpm as the package manager
Follow these steps to set up and run the project locally:
git clone https://github.com/eten-tech-foundation/fluent-web.git
cd fluent-webThe project uses Node.js 24.13.0 as specified in the .nvmrc file. If you're using nvm, run:
nvm install # This will read the .nvmrc file and install the specified version
nvm use # This will switch to the version specified in .nvmrcpnpm installpnpm start
# or
pnpm devThe application will be available at http://localhost:5173 by default.
This project supports containerized development using Docker or Podman. The container setup provides a consistent, isolated environment with hot-reload support.
Linux/macOS:
# Initial setup - create .env file
./fweb.sh setup
# Start the containerized dev server
./fweb.sh upWindows (PowerShell):
# Initial setup - create .env file
.\fweb.ps1 setup
# Start the containerized dev server
.\fweb.ps1 upThe application will be available at http://localhost:5173.
| Command | Description |
|---|---|
up |
Build image and start container |
down |
Stop and remove container |
restart |
Restart the container |
logs |
Tail container logs |
status |
Show container status |
shell |
Open shell inside container |
test |
Run test suite inside container |
lint |
Run ESLint inside container |
lint:fix |
Run ESLint with auto-fix |
format |
Format code with Prettier |
typecheck |
Run TypeScript type checking |
precheck |
Run all checks (lint, format, typecheck, test) |
preview |
Preview production build |
clean |
Remove container and volumes |
fresh |
Complete reset (container, volumes, image) |
build |
Rebuild container image |
run <script> |
Run any pnpm script inside container |
Configure the container via environment variables:
| Variable | Default | Description |
|---|---|---|
CONTAINER_NAME |
fluent-web |
Container name |
IMAGE_NAME |
fluent-web |
Image name |
PORT |
5173 |
Host port to bind |
VITE_API_URL |
http://localhost:9999 |
API URL for the app |
WEB_CONTEXT |
project root | Path for config files |
Example:
PORT=3000 VITE_API_URL=http://api.example.com ./fweb.sh up- Rootless execution: Runs as non-root user (UID 1001)
- Read-only filesystem: Container root is read-only with tmpfs for
/tmp - Security hardened: Drops all capabilities, prevents privilege escalation
- Volume caching:
node_modulesand cache directories are persisted in named volumes - Hot reload: Source code changes are reflected immediately
Port already in use:
PORT=3000 ./fweb.sh up # Use a different portContainer fails to start:
./fweb.sh fresh # Complete rebuild from scratchCheck container logs:
./fweb.sh logspnpm startorpnpm dev- Start the development serverpnpm preview- Preview the production build
pnpm build- Build the application for productionpnpm build:analyze- Build with bundle analysis
pnpm set-env <environment>- Switch between environments (local, development, staging, production)
See Environment Configuration for detailed documentation on how to set up and use environment variables.
pnpm lint- Run ESLint to check for code issuespnpm lint:fix- Run ESLint and automatically fix issuespnpm format- Format code with Prettierpnpm format:check- Check formatting without making changespnpm typecheck- Run TypeScript type checking
pnpm deps:clean- Prune and reinstall dependenciespnpm deps:reset- Remove node_modules and lock file, then reinstall
- This project uses TypeScript for type safety
- We follow ESLint and Prettier for code quality and formatting
- Git commits are checked using Husky and lint-staged
- The project enforces the Node.js version specified in
.nvmrcand package.json - Line endings are standardized to LF (Unix-style) via:
.gitattributes: Enforces LF line endings in Git.editorconfig: Sets consistent coding styles across editors.prettierrc.js: Configures Prettier to use LF- VS Code settings: Configures the editor to use LF
- Husky pre-commit hook: Automatically converts CRLF to LF
This project enforces consistent line endings (LF) across all platforms to prevent issues with mixed line endings, especially on cross-platform teams.
We have multiple layers of protection against line ending issues:
.gitattributesfile: Enforces LF line endings for all text files- Pre-commit hook: Automatically converts CRLF to LF for staged files before commit
Windows users should configure Git to respect the .gitattributes file by running:
git config --global core.autocrlf false
git config --global core.eol lfIf you experience line ending issues:
-
Check file status with:
git ls-files --eol | grep -E 'w/(mixed|crlf)'
-
If you need to fix line endings for the entire repository:
# First commit or stash your changes git rm --cached -r . git reset --hard git add . git commit -m "Normalize line endings"
-
For new clones, after configuring Git as above:
git clone --config core.autocrlf=false <repository-url>
If you encounter errors related to Node.js version:
# Make sure you're using the correct Node.js version
nvm use
# Or install it if not available
nvm installIf you encounter dependency-related errors:
# Try a clean install
pnpm deps:clean
# If that doesn't work, try a more aggressive reset
pnpm deps:resetSee the LICENSE file for details.