Skip to content

nomtek/RefinedAR

Repository files navigation

RefinedAR

AR furniture visualization platform — view 3D furniture models in augmented reality via mobile cameras, QR codes, and an embeddable web component.

What is RefinedAR?

RefinedAR is an open-source web platform that lets users upload 3D furniture models and visualize them in augmented reality through their mobile camera. Key capabilities:

  • Upload GLTF/GLB models and convert them to AR-ready formats (USDZ for iOS, GLB for Android)
  • Generate QR codes that open the AR viewer on mobile
  • Embed the AR viewer in any website via the refined-ar-viewer web component
  • Manage products and users through a full-featured dashboard

The project is a monorepo containing 6 repositories that work together as a complete platform.

Table of Contents


Repositories Overview

Repository Type Port Description
refined-ar-backend NestJS API 4000 Core API server (auth, products, file storage)
refined-ar-next-js Next.js 3000 Main dashboard application
refined-ar-converter-api NestJS API 5001 3D model conversion microservice
refined-ar-converter-app Next.js 3001 Converter web UI
web-component Stencil.js Embeddable AR viewer widget
refined-commons TypeScript Shared types and configuration

Architecture

┌─────────────────────────────────────────────────────────────────┐
│                         Frontend Layer                          │
│  ┌─────────────────────┐     ┌─────────────────────────────┐   │
│  │ refined-ar-next-js  │     │ refined-ar-converter-app    │   │
│  │     (Port 3000)     │     │       (Port 3001)           │   │
│  └──────────┬──────────┘     └──────────────┬──────────────┘   │
└─────────────┼───────────────────────────────┼──────────────────┘
              │                               │
              ▼                               ▼
┌─────────────────────────────────────────────────────────────────┐
│                         Backend Layer                           │
│  ┌─────────────────────┐     ┌─────────────────────────────┐   │
│  │ refined-ar-backend  │     │ refined-ar-converter-api    │   │
│  │     (Port 4000)     │     │       (Port 5001)           │   │
│  └──────────┬──────────┘     └──────────────┬──────────────┘   │
└─────────────┼───────────────────────────────┼──────────────────┘
              │                               │
              ▼                               ▼
┌─────────────────────────────────────────────────────────────────┐
│                      Infrastructure Layer                        │
│  ┌────────────┐  ┌────────────┐  ┌────────────────────────────┐ │
│  │ PostgreSQL │  │   Redis    │  │         AWS S3             │ │
│  │  (54321)   │  │   (6379)   │  │    (File Storage)          │ │
│  └────────────┘  └────────────┘  └────────────────────────────┘ │
└─────────────────────────────────────────────────────────────────┘

┌─────────────────────────────────────────────────────────────────┐
│                       Embeddable Widget                         │
│  ┌─────────────────────────────────────────────────────────┐   │
│  │   <refined-ar-viewer model-id="..." />                  │   │
│  │   Embed in any website to enable AR viewing             │   │
│  └─────────────────────────────────────────────────────────┘   │
└─────────────────────────────────────────────────────────────────┘

Tech Stack

Category Version
Runtime Node.js 22.x LTS
Backend Framework NestJS 10.x
Frontend Framework Next.js 15.x
Web Components Stencil.js 4.x
Database PostgreSQL 14
Cache/Queue Redis 7
ORM TypeORM 0.3.x
Authentication JWT + Passport
File Storage AWS S3
Containerization Docker

Prerequisites

  • Docker and Docker Compose v2.x (recommended for running the full stack)
  • Node.js 22.x LTS (for local development without Docker)
  • Git
  • AWS account with S3 access (for file storage)

Quick Start — Docker Compose (Recommended)

Step 1: Clone the Repository

git clone https://github.com/nomtek/refined-ar.git
cd refined-ar

The repository structure:

refined-ar/
├── docker-compose.yml
├── refined-ar-backend/
├── refined-ar-next-js/
├── refined-ar-converter-api/
├── refined-ar-converter-app/
├── refined-commons/
└── web-component/

Step 2: Build Shared Package

cd refined-commons
npm install
npm run build
cd ..

Step 3: Create Environment Files

3.1 Backend Database Config

Create refined-ar-backend/.docker-compose.env:

POSTGRES_USER=postgres
POSTGRES_PASSWORD=your_secure_password_here
POSTGRES_DB=refined_ar_dev

3.2 Backend API Config

Create refined-ar-backend/.env:

# Database
TYPEORM_CONNECTION=postgres
TYPEORM_HOST=postgres
TYPEORM_USERNAME=postgres
TYPEORM_PASSWORD=your_secure_password_here
TYPEORM_DATABASE=refined_ar_dev
TYPEORM_PORT=5432
TYPEORM_SYNCHRONIZE=false
TYPEORM_LOGGING=true
TYPEORM_MIGRATIONS_DIR=dist/src/migrations
TYPEORM_MIGRATIONS=dist/src/migrations/*.js

# Authentication
JWT_SECRET=your-jwt-secret-key-minimum-32-chars

# URLs
BASE_URL=http://localhost:4000
FRONTEND_HOST=http://localhost:3000
CORS_WHITELIST=http://localhost:3000,http://localhost:3001
PORT=4000

# AWS S3 (Required)
DEFAULT_S3_BUCKET_NAME=your-bucket-name
AWS_ACCESS_KEY_ID=your-access-key
AWS_SECRET_ACCESS_KEY=your-secret-key

# Redis
REDIS_URL=redis://redis:6379

# Token Settings
ACCESS_TOKEN_EXPIRATION=12h
REFRESH_TOKEN_EXPIRATION=30d

# Product Limits
PREMIUM_USER_MAX_PRODUCTS=30
DEFAULT_USER_MAX_PRODUCTS=15

3.3 Converter API Config

Create refined-ar-converter-api/.env:

# AWS Configuration
AWS_BUCKET_NAME=your-bucket-name
AWS_REGION=eu-central-1
AWS_ACCESS_KEY_ID=your-access-key
AWS_SECRET_ACCESS_KEY=your-secret-key

# API Key (Required - generate a secure random string)
CONVERTER_API_KEY=your-secure-api-key-here-32chars

# CORS Configuration
CORS_WHITELIST=http://localhost:3000,http://localhost:3001

# Environment
NODE_ENV=development
PORT=5000

3.4 Next.js Dashboard Config

Create refined-ar-next-js/.env.local:

NEXT_PUBLIC_API_URL=http://localhost:4000
NEXT_PUBLIC_CONVERTER_API_URL=http://localhost:5001
NEXT_PUBLIC_CONVERTER_API_KEY=your-secure-api-key-here-32chars

3.5 Converter App Config

Create refined-ar-converter-app/.env.local:

NEXT_PUBLIC_API_URL=http://localhost:5001

Step 4: Build and Run

docker compose build
docker compose up

Step 5: Verify Services

Service URL Notes
Main Dashboard http://localhost:3000 Login/register page
Backend API http://localhost:4000 REST API
Swagger Docs http://localhost:4000/api API documentation
Converter API http://localhost:5001 Requires X-API-Key header
Converter App http://localhost:3001 Standalone converter UI

Using the Widget

The refined-ar-viewer web component allows you to embed AR viewing capability in any website.

Quick Demo

See the included index.html for a working example:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>RefinedAR Demo</title>

    <!-- Load the RefinedAR widget -->
    <script type="module" src="https://your-domain.com/widget/refinedar.esm.js"></script>
</head>
<body>
<refined-ar-viewer
        model-id="your-product-uuid"
        lang="en"
/>
</body>
</html>

Embed in Your Website

Step 1: Add the embedding page's origin to the backend CORS whitelist

The widget makes API calls to the backend, so the page embedding it must be in the backend's CORS_WHITELIST. For example, if embedding on https://my-shop.com:

CORS_WHITELIST=https://your-domain.com,https://my-shop.com

Step 2: Add the script tag

<script type="module" src="https://your-domain.com/widget/refinedar.esm.js"></script>

Step 3: Add the component

<refined-ar-viewer
        model-id="6c1da829-20b2-4cd8-8bc4-f4eba1c69173"
        lang="en"
        button-style="black"
/>

Widget Properties

Property Attribute Type Default Description
modelId model-id string Required. Product UUID from the backend API
lang lang string "en" Language code (en, de, fr, etc.)
buttonStyle button-style string "black" "black", "white", or "custom"
buttonTitle button-title string "View in AR" Custom button text
modalTitle modal-title string Auto QR modal title
modalDescription modal-description string Auto QR modal description
modalButtonTitle modal-button-title string Auto QR modal close button text
gaTracker ga-tracker string Google Analytics (Universal) tracking ID
gtmTracker gtm-tracker string Google Tag Manager container ID

Full Example with Custom Styling

<refined-ar-viewer
        lang="en"
        model-id="6c1da829-20b2-4cd8-8bc4-f4eba1c69173"
        button-style="white"
        button-title="View in AR"
        modal-title="Scan to View in AR"
        modal-description="Scan this QR code with your mobile device"
        modal-button-title="Close"
        ga-tracker="UA-XXXXXXXXX-X">
</refined-ar-viewer>

Event Handling

<refined-ar-viewer model-id="your-model-id" lang="en"></refined-ar-viewer>

<script>
    const viewer = document.querySelector('refined-ar-viewer');

    viewer.addEventListener('buttonClicked', (event) => {
        console.log('Button clicked:', event.detail.type); // 'AR' or 'QR'
    });
</script>

How to Get a Model ID

  1. Via Dashboard (http://localhost:3000): Upload a product with a 3D model
  2. Via Converter App (http://localhost:3001): Upload and convert a GLTF/GLB file
  3. Via API: POST to /api/converter/convert with X-API-Key header

Self-Hosting the Widget

When self-hosting, update the widget configuration in web-component/config/globalScript.prod.ts:

export const config: EnvironmentConfig = {
    api: 'https://api.your-domain.com/product/',
    refinedLogoUrl: 'https://your-domain.com/images/refined-logo.svg',
    refinedQrLogo: 'https://your-domain.com/images/qr-refined-logo.svg',
    refinedLandingUrl: 'https://your-domain.com',
    refinedViewUrl: 'https://your-domain.com/view/',
};

Then build the widget:

cd web-component
npm install
npm run buildProd

The compiled files will be in web-component/dist/refinedar/.


Production Deployment

Using Pre-built Docker Images (Recommended)

Deploy the full stack in under 5 minutes using pre-built images from GitHub Container Registry.

Available Images

Image Description
ghcr.io/nomtek/refined-ar-backend Core API server (NestJS)
ghcr.io/nomtek/refined-ar-converter-api 3D model conversion microservice
ghcr.io/nomtek/refined-ar-dashboard Main dashboard (Next.js)
ghcr.io/nomtek/refined-ar-converter-app Converter web UI (Next.js)

Image Tags

Every push to the default branch publishes images with two tags:

Tag Example Description
latest ghcr.io/nomtek/refined-ar-backend:latest Always points to the newest build
<commit-sha> ghcr.io/nomtek/refined-ar-backend:<sha> Pinned to a specific commit

Use :latest for the simplest setup — it always pulls the newest version. To pin a specific version, find the commit SHA from GitHub Packages and use it as the tag instead.

Quick Start

# 1. Get the deployment files
curl -O https://raw.githubusercontent.com/nomtek/refined-ar/main/docker-compose.ghcr.yml
curl -O https://raw.githubusercontent.com/nomtek/refined-ar/main/.env.production.example

# 2. Configure
cp .env.production.example .env
# Edit .env with your values (see Environment Variables Reference below)

# 3. Deploy
docker compose -f docker-compose.ghcr.yml --env-file .env up -d

# 4. Run database migrations
docker exec $(docker ps -qf "name=backend") npx typeorm migration:run --dataSource ./dist/src/data-source.js

# 5. Open http://localhost:3000

All NEXT_PUBLIC_* variables are injected at container startup — no rebuilding needed.

To pin a specific version, replace :latest with the commit SHA tag in docker-compose.ghcr.yml for each service. You can find available tags in GitHub Packages.

S3-Compatible Storage (MinIO, R2, DigitalOcean Spaces, etc.)

RefinedAR works with any S3-compatible storage. Add these to your .env:

S3_ENDPOINT_URL=https://your-s3-endpoint.com   # e.g. http://minio:9000
S3_FORCE_PATH_STYLE=true                        # required for most S3-compatible providers

Leave both empty/unset for standard AWS S3.

Required Environment Variables

See .env.production.example for the full list with comments. The essential ones:

Variable Description
POSTGRES_PASSWORD Database password
JWT_SECRET Auth signing secret (64+ chars)
BASE_URL Public backend URL (e.g. https://api.your-domain.com)
FRONTEND_HOST Public dashboard URL (e.g. https://your-domain.com)
CORS_WHITELIST Comma-separated allowed origins
AWS_ACCESS_KEY_ID S3 credentials
AWS_SECRET_ACCESS_KEY S3 credentials
AWS_BUCKET_NAME S3 bucket name
CONVERTER_API_KEY Converter API auth key (32+ chars)
NEXT_PUBLIC_API_URL Backend URL (as seen by browsers)
NEXT_PUBLIC_CONVERTER_API_URL Converter API URL (as seen by browsers)

Build Your Own Images

If you want to customize the images or use your own registry:

# Clone the repo
git clone https://github.com/nomtek/refined-ar.git
cd refined-ar

# Build all images
docker compose build

# Or build individually
docker build -f refined-ar-backend/Dockerfile -t my-registry/refined-ar-backend:latest refined-ar-backend
docker build -f refined-ar-next-js/refined-ar-next-js/Dockerfile -t my-registry/refined-ar-dashboard:latest .

Deploy with Coolify

Coolify is a self-hosted PaaS that simplifies deployment.

  1. Create a Docker Compose resource in Coolify
  2. Paste contents of docker-compose.ghcr.yml
  3. Add environment variables from .env.production.example
  4. Deploy

Hosting the Widget

After deploying, the AR viewer widget is served from the dashboard at:

https://your-domain.com/widget/refinedar.esm.js

Embed it in any website:

<script type="module" src="https://your-domain.com/widget/refinedar.esm.js"></script>
<refined-ar-viewer model-id="<product-uuid>" lang="en" />

Manual Setup (Without Docker)

Backend (refined-ar-backend)

cd refined-ar-backend

# Start PostgreSQL and Redis via Docker
docker compose up postgres redis -d

# Install and run
npm install
npm run build
npm run start:dev

Dashboard (refined-ar-next-js)

cd refined-ar-next-js
npm install
npm run dev

Converter API (refined-ar-converter-api)

cd refined-ar-converter-api
npm install
npm run build
npm run start:dev

Note: USDZ conversion requires the usd_from_gltf binary. The Docker image includes this, but for local development you may need to install it separately or conversions will only produce GLB files.

Converter App (refined-ar-converter-app)

cd refined-ar-converter-app
npm install
npm run dev

Web Component (web-component)

cd web-component
npm install
npm run start      # Dev server with hot reload
# or
npm run buildDev   # Build for development (points to localhost:4000)
npm run buildProd  # Build for production

Database Operations

Access PostgreSQL

# Via Docker
docker exec -it refined-ar-db psql -U postgres -d refined_ar_dev

# Create test database
docker exec -it refined-ar-db psql -U postgres -c "CREATE DATABASE refined_ar_test;"

Run Migrations

Migrations run automatically on backend startup. To run manually:

docker exec -it refined-ar-backend bash
npm run build
npx typeorm migration:run --dataSource ./dist/src/data-source.js

Environment Variables Reference

Database (PostgreSQL)

Variable Required Default Description
POSTGRES_USER No postgres Database user
POSTGRES_PASSWORD Yes Database password
POSTGRES_DB No refined_ar Database name

refined-ar-backend

Database Connection

Variable Required Default Description
TYPEORM_CONNECTION No postgres Database type
TYPEORM_HOST Yes Database host (use postgres in Docker)
TYPEORM_USERNAME Yes Database username
TYPEORM_PASSWORD Yes Database password
TYPEORM_DATABASE Yes Database name
TYPEORM_PORT No 5432 Database port
TYPEORM_SYNCHRONIZE No false Auto-sync schema (keep false in production)
TYPEORM_LOGGING No true Enable query logging
TYPEORM_MIGRATIONS_DIR No dist/src/migrations Migrations directory
TYPEORM_MIGRATIONS No dist/src/migrations/*.js Migration files pattern
DB_SSL_CA_PATH No Path to SSL CA certificate for database

Authentication & Security

Variable Required Default Description
JWT_SECRET Yes Secret for JWT signing (64+ chars recommended)
ACCESS_TOKEN_EXPIRATION No 12h JWT access token expiry
REFRESH_TOKEN_EXPIRATION No 30d JWT refresh token expiry
COOKIE_DOMAIN No Cookie domain for cross-subdomain auth (e.g. .your-domain.com)

URLs & Networking

Variable Required Default Description
BASE_URL Yes http://localhost:4000 Public backend URL
FRONTEND_HOST Yes Public frontend URL (used in emails, redirects)
CORS_WHITELIST Yes Comma-separated allowed origins
PORT No 4000 HTTP port

AWS S3 / S3-Compatible Storage

Variable Required Default Description
AWS_ACCESS_KEY_ID Yes S3 access key
AWS_SECRET_ACCESS_KEY Yes S3 secret key
DEFAULT_S3_BUCKET_NAME Yes S3 bucket for file storage
AWS_REGION No eu-west-2 AWS region
S3_ENDPOINT_URL No Custom S3 endpoint (for MinIO, R2, DigitalOcean Spaces)
S3_FORCE_PATH_STYLE No false Set true for most S3-compatible providers

Redis

Variable Required Default Description
REDIS_HOST No redis Redis host
REDIS_PORT No 6379 Redis port
REDIS_PASSWORD No Redis password (if authentication enabled)

Product Limits

Variable Required Default Description
PREMIUM_USER_MAX_PRODUCTS No 30 Max products for premium users
DEFAULT_USER_MAX_PRODUCTS No 15 Max products for regular users
MODEL_MAX_FILE_SIZE No 104857600 Max file upload size in bytes (100 MB)

Email (Mailgun) — Optional

Variable Required Default Description
MAILGUN_API_KEY No Mailgun API key
MAILGUN_DOMAIN No Mailgun sending domain
MAILGUN_BASE_URL No https://api.eu.mailgun.net Mailgun API base URL
EMAIL_SENDER_USERNAME No no-reply@example.com Sender email address

Notifications — Optional

Variable Required Default Description
SLACK_WEBHOOK_URL No Slack incoming webhook URL
SLACK_WEBHOOK_ENABLED No false Enable Slack notifications

Payments — Optional

Variable Required Default Description
STRIPE_SECRET_KEY No Stripe secret key for payment processing

refined-ar-converter-api

Variable Required Default Description
AWS_BUCKET_NAME Yes S3 bucket for converted files
AWS_ACCESS_KEY_ID Yes S3 access key
AWS_SECRET_ACCESS_KEY Yes S3 secret key
AWS_REGION No eu-central-1 AWS region
CONVERTER_API_KEY Yes API key for authentication (32+ chars)
CORS_WHITELIST Yes Comma-separated allowed origins
S3_ENDPOINT_URL No Custom S3 endpoint (for MinIO, R2, etc.)
S3_FORCE_PATH_STYLE No false Set true for S3-compatible providers
PORT No 5000 HTTP port
NODE_ENV No development Environment (development or production)

refined-ar-next-js (Dashboard)

All NEXT_PUBLIC_* variables are injected at container startup via docker-entrypoint.sh — no rebuild needed.

Required

Variable Required Default Description
NEXT_PUBLIC_API_URL Yes http://localhost:4000 Backend API URL (as seen by browsers)
NEXT_PUBLIC_CONVERTER_API_URL Yes http://localhost:5000 Converter API URL (as seen by browsers)
NEXT_PUBLIC_CONVERTER_API_KEY Yes Converter API key (must match CONVERTER_API_KEY)

Branding — Optional

Variable Required Default Description
NEXT_PUBLIC_APP_NAME No MyApp Application name shown in UI
NEXT_PUBLIC_WEBSITE_URL No https://your-website.com Company website URL
NEXT_PUBLIC_CONTACT_EMAIL No Contact email address
NEXT_PUBLIC_MANUAL_URL No /guide Help/documentation URL
NEXT_PUBLIC_PRIVACY_POLICY_URL No Privacy policy URL
NEXT_PUBLIC_PRODUCTS_COUNT_LIMIT No 1 Product limit display

Analytics & Error Tracking — Optional

Variable Required Default Description
NEXT_PUBLIC_GOOGLE_ANALYTICS No Google Analytics tracking ID
NEXT_PUBLIC_HOTJAR No Hotjar analytics tracking ID
NEXT_PUBLIC_AIRBRAKE_PROJECT_ID No Airbrake error tracking project ID
NEXT_PUBLIC_AIRBRAKE_PROJECT_KEY No Airbrake error tracking project key

refined-ar-converter-app

All NEXT_PUBLIC_* variables are injected at container startup via docker-entrypoint.sh — no rebuild needed.

Variable Required Default Description
NEXT_PUBLIC_API_URL Yes http://localhost:5001/api/converter/convert Converter API endpoint
NEXT_PUBLIC_CONVERTER_API_KEY Yes API authentication key (must match CONVERTER_API_KEY)
NEXT_PUBLIC_APP_NAME No converter.AR Application name
NEXT_PUBLIC_WEBSITE_URL No https://www.refined.ar/ Branding website URL
NEXT_PUBLIC_WIDGET_URL No Embedded widget JavaScript URL
NEXT_PUBLIC_SITE_URL No Website URL for SEO meta tags
NEXT_PUBLIC_OG_IMAGE_URL No Open Graph image URL
NEXT_PUBLIC_CONTACT_EMAIL No Contact email address
NEXT_PUBLIC_FOOTER_TEXT No Custom footer text
NEXT_PUBLIC_MANUAL_URL No /guide Help guide URL
NEXT_PUBLIC_SOCIAL_LINKEDIN No LinkedIn profile URL
NEXT_PUBLIC_SOCIAL_TWITTER No Twitter profile URL
NEXT_PUBLIC_SOCIAL_FACEBOOK No Facebook profile URL
NEXT_PUBLIC_GOOGLE_ANALYTICS No Google Analytics tracking ID
NEXT_PUBLIC_HOTJAR No Hotjar analytics tracking ID
NEXT_PUBLIC_AIRBRAKE_PROJECT_ID No Airbrake error tracking project ID
NEXT_PUBLIC_AIRBRAKE_PROJECT_KEY No Airbrake error tracking project key

Port Mapping

Service Container Port Host Port
PostgreSQL 5432 54321
Redis 6379 6379
Backend API 4000 4000
Converter API 5000 5001
Dashboard 3000 3000
Converter App 3000 3001

Security Notes

Password Requirements

  • Minimum 12 characters
  • At least one uppercase letter (A-Z)
  • At least one lowercase letter (a-z)
  • At least one digit (0-9)
  • At least one special character (@$!%*?&)

API Authentication

  • Converter API requires X-API-Key header on all requests
  • Use a secure random string of 32+ characters for CONVERTER_API_KEY
  • Never expose API keys in client-side code (use environment variables)

Secrets Management

  • Never commit .env files with real credentials
  • Use .env.example files as templates
  • Rotate secrets regularly in production
  • Consider using a secrets manager (AWS Secrets Manager, HashiCorp Vault)

Troubleshooting

Docker Build Fails

docker compose down
docker system prune -f
docker compose build --no-cache
docker compose up

Port Already in Use

lsof -i :4000
kill -9 <PID>

Database Connection Issues

docker exec -it refined-ar-db psql -U postgres -c "SELECT 1"
docker compose logs postgres

Converter API Returns 401

Ensure:

  1. CONVERTER_API_KEY is set in .env
  2. Requests include X-API-Key: <your-key> header

Widget Not Loading

  1. Check browser console for CORS errors
  2. Verify the widget script URL is correct
  3. Ensure model-id is a valid product UUID from your backend
  4. Check that the backend API is accessible from the browser

Contributing

Pull requests are welcome! For significant changes, please open an issue first.

  • Code style enforced with ESLint and Prettier — run npm run lint
  • All existing tests must pass
  • Add tests for new functionality

License

MIT


Links

About

No description, website, or topics provided.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

 
 
 

Contributors