xRegistry Viewer
November 4, 2025 ยท View on GitHub
This is an Angular application that visualizes and explores data from an xRegistry-compliant API. It provides a user-friendly interface to browse registry groups, resources, versions, and detailed documents.
The application is model-driven, using the metadata provided by the xRegistry API's model endpoint and dynamically adapts its UI based on the resource schemas and types.
You can point the application to one of multiple xRegistry endpoints. The application will consolidate and display data from the selected registries in a unified interface, grouping metadata by model and groups.
The repository builds a Docker image with a production-ready Angular application served via a Node.js + Express server, including an API proxy for cross-origin requests.
๐ Table of Contents
- Features
- Prerequisites
- Quick Start
- Development Guide
- Docker Deployment
- Testing
- Architecture
- Contributing
โจ Features
- Browse Registry Data: Explore group types, groups, resources, and versions
- Detailed Views: View resource documents, schemas, and metadata
- Search & Filter: Quick search and advanced filtering capabilities
- Smart Display Modes: Automatic card/list view based on content density
- Sticky Page Reloads: Maintains your location across page refreshes (see below)
- API Proxy: Built-in proxy for secure cross-origin API requests
- Health Monitoring: Health check endpoints for production monitoring
๐ Sticky Reloads
The application preserves your navigation state during page refreshes, making development and bookmarking easier.
Use Cases:
- Bookmarking deep links to specific resources
- Development workflow with hot reloads
- Sharing URLs that point to specific registry items
How It Works:
- Current route is stored in browser session storage
- On page reload, app redirects to root and then auto-navigates to previous location
- Route storage is cleared on explicit home navigation to prevent redirect loops
Example:
Navigate to: /schemagroups/Contoso.ERP/schemas/Contoso.ERP.CancellationData
Reload page โ automatically returns to the same resource detail view
๐ฆ Prerequisites
Before you begin, ensure you have the following installed:
- Node.js: v20.19.3 or higher (LTS recommended)
- npm: v10.0.0 or higher (comes with Node.js)
- Angular CLI: v19.0.0 or higher
- Docker: v20.10.0 or higher (optional, for containerized deployment)
- Docker Compose: v2.0.0 or higher (optional, for containerized deployment)
Check your versions:
node --version # Should show v20.x.x or higher
npm --version # Should show v10.x.x or higher
ng version # Should show Angular CLI 19.x.x
docker --version # Optional: for Docker deployment
Install Angular CLI globally (if not already installed):
npm install -g @angular/cli@19
๐ Quick Start
1. Clone the Repository
git clone https://github.com/xregistry/viewer.git
cd viewer
2. Install Dependencies
npm install
This will install all required packages listed in package.json, including:
- Angular 19 framework and dependencies
- FluentUI Web Components for UI
- RxJS for reactive programming
- Development tools (TypeScript, Jest, etc.)
3. Start Development Server
npm start
# or
ng serve
The application will be available at: http://localhost:4200/
The development server includes:
- Hot Module Replacement (HMR): Changes automatically reflected in browser
- Source Maps: For easier debugging
- Live Reload: Browser refreshes on file changes
๐ป Development Guide
Project Structure
xregistry-viewer/
โโโ src/
โ โโโ app/
โ โ โโโ components/ # UI components
โ โ โโโ services/ # Business logic and API calls
โ โ โโโ models/ # TypeScript interfaces and types
โ โ โโโ utils/ # Helper functions
โ โ โโโ app.routes.ts # Application routing
โ โโโ assets/ # Static files (images, fonts, etc.)
โ โโโ environments/ # Environment-specific configuration
โ โโโ styles/ # Global SCSS styles
โ โโโ index.html # Main HTML entry point
โโโ docs/ # Documentation
โโโ public/ # Public assets (favicon, config.json)
โโโ server.js # Production Express server
โโโ Dockerfile # Docker build configuration
โโโ docker-compose.yml # Docker Compose orchestration
Key Technologies
- Angular 19: Frontend framework with standalone components
- TypeScript 5.7: Strongly-typed JavaScript superset
- FluentUI Web Components: UI component library
- RxJS 7: Reactive programming library
- SCSS: CSS preprocessor for styling
- Jest: Testing framework
- Express.js 4: Production server (Docker deployment)
Development Workflow
-
Create a Feature Branch
git checkout -b feature/my-new-feature -
Make Changes
- Edit files in
src/app/ - Follow Angular style guide
- Use TypeScript strict mode
- Edit files in
-
Test Your Changes
npm test # Run unit tests npm run test:watch # Watch mode for TDD -
Build for Production
npm run build-prod # Create production build -
Commit and Push
git add . git commit -m "feat: add new feature" git push origin feature/my-new-feature
โ๏ธ Configuration
API Configuration
The application needs to be configured with your xRegistry API endpoint.
Option 1: Via UI (Recommended for Development)
- Click the Settings icon (โ๏ธ) in the application header
- Navigate to API Configuration
- Enter your API base URL (e.g.,
https://myregistry.example.com) - Click Save Changes
Configuration is persisted in browser local storage and survives page reloads.
Option 2: Via config.json (Recommended for Production)
For production deployments, configure the API via public/config.json:
{
"apiBaseUrl": "https://your-xregistry-api.com",
"registryEndpoint": "https://your-xregistry-api.com/api/v1"
}
The application loads this configuration on startup. This approach is ideal for:
- Docker deployments
- CI/CD pipelines
- Environment-specific configurations
- Configuration without rebuilding the application
Option 3: Environment Files (Build-Time Configuration)
For build-time configuration, edit environment files:
Development (src/environments/environment.ts):
export const environment = {
production: false,
apiBaseUrl: 'https://dev.myregistry.example.com'
};
Production (src/environments/environment.prod.ts):
export const environment = {
production: true,
apiBaseUrl: 'https://myregistry.example.com'
};
Note: Environment files are baked into the build, requiring a rebuild to change configuration.
Proxy Configuration
The built-in proxy allows the application to make cross-origin API requests securely. Configure proxy targets in public/config.json:
{
"proxyPrefixes": [
"https://myregistry.example.com",
"https://api.example.com"
]
}
The application will route requests through /proxy?target=<url> for these prefixes.
๐จ Build
Development Build
npm run build
# or
ng build
Output: dist/xregistry-viewer/ (non-optimized, with source maps)
Production Build
npm run build-prod
# or
ng build --configuration production
Output: dist/xregistry-viewer/ (optimized, minified, tree-shaken)
Production build features:
- Ahead-of-Time (AOT) Compilation: Pre-compiles templates for faster rendering
- Tree Shaking: Removes unused code
- Minification: Reduces file sizes
- Code Splitting: Lazy-loaded routes for optimal performance
- Server-Side Rendering (SSR) Support: Pre-renders pages for SEO and performance
- Compression: Gzip/Brotli ready
Build artifacts location:
dist/xregistry-viewer/
โโโ browser/ # Client-side application
โ โโโ index.html
โ โโโ main.*.js
โ โโโ polyfills.*.js
โ โโโ styles.*.css
โโโ server/ # SSR server (if enabled)
๐ณ Docker Deployment
Pre-built Docker images are automatically published to GitHub Container Registry (ghcr.io) on every push to main and for tagged releases. Images are signed with Sigstore cosign for supply chain security.
Pull the latest image:
docker pull ghcr.io/xregistry/viewer:latest
The application uses a unified architecture with a single Node.js + Express server that handles:
- Static file serving (Angular application)
- API proxy (for cross-origin requests)
- Health monitoring
- Configuration loading
- Gzip compression
Architecture Overview
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Docker Container (Port 4000) โ
โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Express.js Server (Node 22) โ โ
โ โ โ โ
โ โ โข Static Files (/dist/xregistry-viewer/) โ โ
โ โ โข API Proxy (/proxy) โ โ
โ โ โข Health Check (/health) โ โ
โ โ โข Config (/config.json) โ โ
โ โ โข Compression (gzip) โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ
โ Alpine Linux (minimal base image) โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
Quick Start with Docker Compose (Recommended)
This is the easiest way to run the application in Docker using the pre-built image.
Step 1: Create a docker-compose.yml
version: '3.8'
services:
xregistry-viewer:
image: ghcr.io/xregistry/viewer:latest
ports:
- "4000:4000"
volumes:
- ./public/config.json:/app/dist/xregistry-viewer/config.json
environment:
- NODE_ENV=production
restart: unless-stopped
Step 2: Start the service
docker-compose up -d
This will:
- Pull the latest pre-built Docker image from GitHub Container Registry
- Start the container in detached mode
- Expose port 4000 on your host machine
- Mount
public/config.jsonas a volume (for easy configuration updates)
Step 3: Verify it's running
# Check container status
docker-compose ps
# View logs
docker-compose logs -f
# Test health endpoint
curl http://localhost:4000/health
Step 4: Access the application
- Application: http://localhost:4000
- Health Check: http://localhost:4000/health
- Config Endpoint: http://localhost:4000/config.json
- Proxy Endpoint: http://localhost:4000/proxy?target=https://api.example.com
Step 5: Stop the service
docker-compose down
Using Pre-built Images (Recommended)
Pull and run the latest image directly:
# Pull the latest image
docker pull ghcr.io/xregistry/viewer:latest
# Run the container
docker run -d \
-p 4000:4000 \
--name xregistry-viewer \
-v $(pwd)/public/config.json:/app/dist/xregistry-viewer/config.json \
ghcr.io/xregistry/viewer:latest
Available image tags:
latest- Latest build from main branchv1.2.3- Specific version (semantic versioning)<sha>- Specific commit SHA
Images are:
- โ Automatically built on every push to main
- โ Signed with Sigstore cosign (supply chain security)
- โ Published to GitHub Container Registry (ghcr.io)
- โ Multi-platform (linux/amd64, linux/arm64)
Build Docker Images Locally (Advanced)
For local development or custom builds:
Using build scripts:
PowerShell (Windows):
.\build-docker.ps1
Bash (Linux/Mac):
chmod +x build-docker.sh
./build-docker.sh
Manual build:
# Build the image
docker build -t xregistry-viewer:latest .
# Run the container
docker run -d \
-p 4000:4000 \
--name xregistry-viewer \
-v $(pwd)/public/config.json:/app/dist/xregistry-viewer/config.json \
xregistry-viewer:latest
# Verify
docker ps
docker logs xregistry-viewer
Docker Image Details
Multi-Stage Build:
The Dockerfile uses a multi-stage build for optimal image size and security:
- Builder Stage: Uses Node 22 to install dependencies and build the application
- Production Stage: Uses Node 22 Alpine (minimal) to run only the production server
Image Size: ~250MB (Alpine Linux + Node 22 + Application)
Base Image: node:22-alpine (minimal, secure, regularly updated)
Configuration in Docker
Mount your config.json file to customize the application without rebuilding:
docker run -d \
-p 4000:4000 \
-v /path/to/your/config.json:/app/dist/xregistry-viewer/config.json \
xregistry-viewer:latest
Example config.json:
{
"apiBaseUrl": "https://myregistry.example.com",
"registryEndpoint": "https://myregistry.example.com/api/v1",
"proxyPrefixes": [
"https://myregistry.example.com",
"https://api.example.com"
]
}
Docker Compose Configuration
Customize docker-compose.yml for your environment:
version: '3.8'
services:
xregistry-viewer:
build: .
ports:
- "4000:4000" # Change port mapping if needed
volumes:
- ./public/config.json:/app/dist/xregistry-viewer/config.json
environment:
- NODE_ENV=production
restart: unless-stopped
healthcheck:
test: ["CMD", "wget", "--quiet", "--tries=1", "--spider", "http://localhost:4000/health"]
interval: 30s
timeout: 10s
retries: 3
Production Deployment
For production deployments, see the comprehensive guide:
Covers:
- Security best practices
- SSL/TLS configuration
- Reverse proxy setup (nginx, Traefik)
- Container orchestration (Kubernetes, Docker Swarm)
- Monitoring and logging
- Backup and recovery
- Performance tuning
๐งช Testing
Unit Tests
Run unit tests with Jest:
npm test
# or
ng test
Watch mode (recommended for development):
npm run test:watch
Generate coverage report:
npm run test:coverage
Coverage report will be generated in coverage/ directory. Open coverage/index.html in a browser to view detailed coverage.
Test Structure:
src/app/
โโโ components/
โ โโโ my-component/
โ โโโ my-component.component.ts
โ โโโ my-component.component.spec.ts โ Test file
โโโ services/
โโโ my-service.service.ts
โโโ my-service.service.spec.ts โ Test file
Writing Tests:
import { TestBed } from '@angular/core/testing';
import { MyService } from './my-service.service';
describe('MyService', () => {
let service: MyService;
beforeEach(() => {
TestBed.configureTestingModule({});
service = TestBed.inject(MyService);
});
it('should be created', () => {
expect(service).toBeTruthy();
});
it('should return correct value', () => {
const result = service.getValue();
expect(result).toBe('expected value');
});
});
Testing in Docker
Test the Docker image before deployment:
# Build and start the container
docker-compose up -d
# Run smoke tests against the container
curl http://localhost:4000/health
curl http://localhost:4000/
# Check logs for errors
docker-compose logs
# Stop the container
docker-compose down
๐๏ธ Architecture
Application Architecture
The application follows Angular best practices with a component-based architecture:
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ Angular Application โ
โ โ
โ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โ
โ โ Components โโโโ Services โ โ
โ โ โ โ โ โ
โ โ - Header โ โ - Registry โ โ
โ โ - Groups โ โ - Document โ โ
โ โ - Resources โ โ - Config โ โ
โ โ - Search โ โ โ โ
โ โโโโโโโโโโโโโโโ โโโโโโโโโโโโโโโโ โ
โ โ โ โ
โ โ โ โ
โ โโโโโโโโดโโโโโโโโโโโโโโโโโดโโโโโโ โ
โ โ Routing (Routes) โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ โ
โ โ โ
โ โโโโโโโโดโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โ โ Models & Interfaces โ โ
โ โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ โ
โโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโโ
โ
โโโโโโโโโโโโโโโโโโโโโโโโ
โ xRegistry API โ
โ (via proxy) โ
โโโโโโโโโโโโโโโโโโโโโโโโ
Key Design Patterns
1. Service Layer Pattern
- Services handle business logic and API calls
- Components only handle presentation logic
- Dependency injection for loose coupling
2. Reactive Programming (RxJS)
- Observables for asynchronous operations
- Operators for data transformation
- Subscription management to prevent memory leaks
3. Component Composition
- Small, focused components
- Parent-child communication via
@Input()and@Output() - Smart components (containers) vs. Dumb components (presentational)
4. Lazy Loading
- Routes loaded on-demand
- Reduces initial bundle size
- Improves performance
Data Flow
User Action โ Component โ Service โ API (via Proxy) โ Response
โ โ
Template Update โ Observable โ RxJS Transform โโ
State Management
- Component state for UI-specific state
- Service state for shared state
- SessionStorage for navigation state (sticky reloads)
- LocalStorage for user preferences (API configuration)
๐ค Contributing
Contribution Workflow
- Fork the repository
- Create a feature branch (
git checkout -b feature/amazing-feature) - Make your changes (follow coding standards)
- Add tests for new functionality
- Run tests and linting (
npm test,npm run lint) - Commit your changes (
git commit -m 'feat: add amazing feature') - Push to your fork (
git push origin feature/amazing-feature) - Open a Pull Request
Commit Message Convention
Follow Conventional Commits:
<type>(<scope>): <subject>
<body>
<footer>
Types:
feat: New featurefix: Bug fixdocs: Documentation changesstyle: Code style changes (formatting, etc.)refactor: Code refactoringtest: Adding or updating testschore: Maintenance tasks
Examples:
feat(search): add fuzzy search functionality
fix(api): resolve CORS issue with proxy
docs(readme): update Docker deployment instructions
test(services): add unit tests for registry service
Code Style
- Follow Angular Style Guide
- Use TypeScript strict mode
- Write meaningful variable and function names
- Add JSDoc comments for public APIs
- Keep functions small and focused (< 50 lines)
- Use async/await instead of callbacks
Pull Request Guidelines
- Title: Clear and descriptive
- Description: What, why, and how
- Tests: Include tests for new features
- Documentation: Update docs if needed
- Screenshots: For UI changes
- Breaking Changes: Clearly marked
๐ License
This project is licensed under the MIT License - see the LICENSE file for details.
๐ Support
- Issues: GitHub Issues
- Discussions: GitHub Discussions
- Documentation: docs/
๐ Acknowledgments
- Angular team for the amazing framework
- xRegistry specification authors
- All contributors to this project
Built with โค๏ธ using Angular 19