standalone

This commit is contained in:
Max Peintner
2025-07-10 13:20:49 +02:00
parent 95fc71d78e
commit c692fa8b99
10 changed files with 399 additions and 0 deletions

View File

@@ -0,0 +1,7 @@
module.exports = {
extends: ["next/core-web-vitals"],
rules: {
"@next/next/no-img-element": "off",
"react/no-unescaped-entities": "off"
}
};

View File

@@ -0,0 +1,58 @@
name: CI
on:
push:
branches: [ main ]
pull_request:
branches: [ main ]
jobs:
test:
runs-on: ubuntu-latest
strategy:
matrix:
node-version: [18.x, 20.x]
steps:
- uses: actions/checkout@v4
- name: Use Node.js ${{ matrix.node-version }}
uses: actions/setup-node@v4
with:
node-version: ${{ matrix.node-version }}
cache: 'npm'
- name: Prepare standalone
run: ./prepare-standalone.sh
- name: Run tests
run: npm run test:unit
- name: Run linting
run: npm run lint
- name: Build application
run: npm run build:standalone
build-docker:
needs: test
runs-on: ubuntu-latest
if: github.ref == 'refs/heads/main'
steps:
- uses: actions/checkout@v4
- name: Prepare standalone
run: ./prepare-standalone.sh
- name: Build Docker image
run: |
docker build -t zitadel-login-ui .
- name: Test Docker image
run: |
docker run --rm -d -p 3000:3000 --name test-container zitadel-login-ui
sleep 10
curl -f http://localhost:3000 || exit 1
docker stop test-container

View File

@@ -0,0 +1,54 @@
# Dependencies
/node_modules
/.pnp
.pnp.js
# Testing
/coverage
# Next.js
/.next/
/out/
# Production
/build
# Misc
.DS_Store
*.pem
# Debug
npm-debug.log*
yarn-debug.log*
yarn-error.log*
# Local env files
.env*.local
# Vercel
.vercel
# TypeScript
*.tsbuildinfo
next-env.d.ts
# Turbo
.turbo
# IDE
.vscode/
.idea/
# Logs
logs
*.log
# Optional npm cache directory
.npm
# Optional eslint cache
.eslintcache
# Package manager locks (we use npm in standalone)
pnpm-lock.yaml
yarn.lock

View File

@@ -0,0 +1,54 @@
# Dockerfile for standalone ZITADEL Login UI
FROM node:18-alpine AS base
# Install dependencies only when needed
FROM base AS deps
RUN apk add --no-cache libc6-compat
WORKDIR /app
# Prepare standalone and install dependencies
COPY prepare-standalone.sh package*.json ./
COPY *.standalone.* ./
RUN ./prepare-standalone.sh
# Rebuild the source code only when needed
FROM base AS builder
WORKDIR /app
COPY --from=deps /app/node_modules ./node_modules
COPY . .
# Prepare standalone configs
RUN ./prepare-standalone.sh --no-install
# Build application
ENV NEXT_TELEMETRY_DISABLED 1
RUN npm run build:standalone
# Production image, copy all the files and run next
FROM base AS runner
WORKDIR /app
ENV NODE_ENV production
ENV NEXT_TELEMETRY_DISABLED 1
RUN addgroup --system --gid 1001 nodejs
RUN adduser --system --uid 1001 nextjs
COPY --from=builder /app/public ./public
# Set the correct permission for prerender cache
RUN mkdir .next
RUN chown nextjs:nodejs .next
# Automatically leverage output traces to reduce image size
COPY --from=builder --chown=nextjs:nodejs /app/.next/standalone ./
COPY --from=builder --chown=nextjs:nodejs /app/.next/static ./.next/static
USER nextjs
EXPOSE 3000
ENV PORT 3000
ENV HOSTNAME "0.0.0.0"
CMD ["node", "server.js"]

View File

@@ -0,0 +1,81 @@
# ZITADEL Login UI - Standalone
This is the standalone version of the ZITADEL Login UI, a Next.js application that provides the authentication interface for ZITADEL.
## Quick Start
### Prerequisites
- Node.js 18+
- npm or pnpm
### Setup
1. **Prepare the standalone environment:**
```bash
./prepare-standalone.sh
```
2. **Start development server:**
```bash
npm run dev
```
3. **Build for production:**
```bash
npm run build:standalone
npm run start
```
## Development
### Available Scripts
- `npm run dev` - Start development server with Turbopack
- `npm run build` - Build for production
- `npm run build:standalone` - Build standalone version with custom base path
- `npm run start` - Start production server
- `npm run test:unit` - Run unit tests
- `npm run lint` - Run linting
- `npm run lint:fix` - Fix linting issues
### Environment Variables
Create a `.env.local` file with your ZITADEL configuration:
```env
ZITADEL_API_URL=https://your-zitadel-instance.com
# Add other required environment variables
```
## Differences from Monorepo Version
This standalone version includes:
- Self-contained configuration files
- Published versions of `@zitadel/client` and `@zitadel/proto` packages
- Standalone build scripts
- Independent dependency management
## Contributing
When contributing to this standalone version:
1. Make changes in the main monorepo first
2. Test changes in the monorepo environment
3. Update the standalone version via subtree push
4. Test the standalone version independently
## Subtree Sync
This repository is maintained as a Git subtree of the main ZITADEL repository.
To sync changes from the main repo:
```bash
# In the main ZITADEL repo
git subtree push --prefix=login/apps/login origin typescript-login-standalone
```
## License
See the main ZITADEL repository for license information.

View File

@@ -0,0 +1,66 @@
{
"name": "@zitadel/login",
"private": true,
"type": "module",
"scripts": {
"dev": "next dev --turbopack",
"test:unit": "vitest",
"test:unit:watch": "vitest --watch",
"lint": "next lint && prettier --check .",
"lint:fix": "prettier --write .",
"build": "next build",
"build:standalone": "NEXT_PUBLIC_BASE_PATH=/ui/v2/login NEXT_OUTPUT_MODE=standalone next build",
"start": "npm run build && next start",
"start:built": "next start",
"clean": "rm -rf .turbo && rm -rf node_modules && rm -rf .next"
},
"dependencies": {
"@headlessui/react": "^2.1.9",
"@heroicons/react": "2.1.3",
"@tailwindcss/forms": "0.5.7",
"@vercel/analytics": "^1.2.2",
"@zitadel/client": "^1.0.0",
"@zitadel/proto": "^1.0.0",
"clsx": "1.2.1",
"copy-to-clipboard": "^3.3.3",
"deepmerge": "^4.3.1",
"lucide-react": "0.469.0",
"moment": "^2.29.4",
"next": "15.4.0-canary.86",
"next-intl": "^3.25.1",
"next-themes": "^0.2.1",
"nice-grpc": "2.0.1",
"qrcode.react": "^3.1.0",
"react": "19.1.0",
"react-dom": "19.1.0",
"react-hook-form": "7.39.5",
"tinycolor2": "1.4.2",
"uuid": "^11.1.0"
},
"devDependencies": {
"@bufbuild/buf": "^1.53.0",
"@testing-library/jest-dom": "^6.6.3",
"@testing-library/react": "^16.3.0",
"@types/ms": "2.1.0",
"@types/node": "^22.14.1",
"@types/react": "19.1.2",
"@types/react-dom": "19.1.2",
"@types/tinycolor2": "1.4.3",
"@types/uuid": "^10.0.0",
"@vercel/git-hooks": "1.0.0",
"eslint": "8.57.1",
"eslint-config-next": "15.4.0-canary.86",
"prettier": "^3.5.3",
"autoprefixer": "10.4.21",
"grpc-tools": "1.13.0",
"jsdom": "^26.1.0",
"make-dir-cli": "4.0.0",
"postcss": "8.5.3",
"prettier-plugin-tailwindcss": "0.6.11",
"sass": "^1.87.0",
"tailwindcss": "3.4.14",
"ts-proto": "^2.7.0",
"typescript": "^5.8.3",
"vitest": "^3.1.2"
}
}

View File

@@ -0,0 +1,27 @@
#!/bin/bash
# Script to prepare standalone version of the login app
set -e
echo "Preparing standalone version..."
# Copy standalone configs
cp package.standalone.json package.json
cp tsconfig.standalone.json tsconfig.json
cp .eslintrc.standalone.cjs .eslintrc.cjs
cp prettier.config.standalone.mjs prettier.config.mjs
cp tailwind.config.standalone.mjs tailwind.config.mjs
# Install dependencies unless --no-install is passed
if [ "$1" != "--no-install" ]; then
echo "Installing dependencies..."
npm install
fi
echo "Standalone version prepared successfully!"
if [ "$1" != "--no-install" ]; then
echo "You can now run:"
echo " npm run dev - Start development server"
echo " npm run build - Build for production"
echo " npm run start - Start production server"
fi

View File

@@ -0,0 +1,8 @@
export default {
semi: true,
trailingComma: "all",
singleQuote: false,
printWidth: 80,
tabWidth: 2,
plugins: ["prettier-plugin-tailwindcss"],
};

View File

@@ -0,0 +1,17 @@
/** @type {import('tailwindcss').Config} */
export default {
content: [
"./src/pages/**/*.{js,ts,jsx,tsx,mdx}",
"./src/components/**/*.{js,ts,jsx,tsx,mdx}",
"./src/app/**/*.{js,ts,jsx,tsx,mdx}",
],
theme: {
extend: {
colors: {
background: "var(--background)",
foreground: "var(--foreground)",
},
},
},
plugins: [require("@tailwindcss/forms")],
};

View File

@@ -0,0 +1,27 @@
{
"compilerOptions": {
"target": "es5",
"lib": ["dom", "dom.iterable", "esnext"],
"allowJs": true,
"skipLibCheck": true,
"strict": true,
"noEmit": true,
"esModuleInterop": true,
"module": "esnext",
"moduleResolution": "bundler",
"resolveJsonModule": true,
"isolatedModules": true,
"jsx": "preserve",
"incremental": true,
"plugins": [
{
"name": "next"
}
],
"paths": {
"@/*": ["./src/*"]
}
},
"include": ["next-env.d.ts", "**/*.ts", "**/*.tsx", ".next/types/**/*.ts"],
"exclude": ["node_modules"]
}