FXN dev

Preview environments, source repos and operational commands. Internal only.

Preview frontends · fxnstudio.com

nxtsmarthomes.fxnstudio.com 3004

NXTSmart.Homes — smart-home blog (imported from WordPress, served from Strapi).

bestlookingskin.fxnstudio.com 3002

BestLooking.Skin — skincare blog preview.

nxtbargains.fxnstudio.com 3001

NXT.Bargains — product-comparison/affiliate blog.

originfacts.fxnstudio.com 3000

OriginFacts — long-form facts/explainer site (renamed from preview.fxnstudio.com).

Backend services · fxnstudio.com

cms.fxnstudio.com 8888

Strapi CMS — content backend for every preview frontend above.

pim.fxnstudio.com 8090

Akeneo PIM — product catalogue master (BigBuy + manual). Runs from local docker-compose; no GitHub mirror.

claw.fxnstudio.com 18789

OpenClaw gateway — scraping/orchestration service.

Production sites hosted on this server

nxt.deals 3010

FXN travel booking platform (Duffel-powered flight + stay search).

nxtsmart.homes apache

Live WordPress site (rehub theme) being migrated to Next.js + Strapi.

Currently running containers

NameImagePortStatus
nxtsmart-homesnode:20-alpine127.0.0.1:3004up
bestlooking-skin-previewnode:20-alpine127.0.0.1:3002up
nxt-bargains-devnode:20-alpine127.0.0.1:3001up
originfacts-com-devnode:20-alpine127.0.0.1:3000up
fxn-chisfis-frontendnode:20-alpine127.0.0.1:3010up nxt.deals
fxn-strapifxnstudio-cms-strapi127.0.0.1:8888up
fxn-postgrespostgres:16-alpineinternalhealthy
akeneo-httpd-1httpd:2.4127.0.0.1:8090up PIM
+ 7 supporting Akeneo containers (fpm, consumer, mysql, elasticsearch, minio, selenium, pubsub-emulator, blackfire)
openclaw-openclaw-gateway-1openclaw:local127.0.0.1:18789-18790healthy

Snapshot at page-render time — use docker ps for live state.

Useful commands

Inspect state
# Running containers
docker ps --format 'table {{.Names}}\t{{.Image}}\t{{.Ports}}\t{{.Status}}'

# All containers (including stopped)
docker ps -a

# Logs (tail + follow)
docker logs --tail 100 -f nxtsmart-homes

# Shell into a container
docker exec -it fxn-strapi sh

# What ports are listening on the host
ss -tlnp | grep -E ':(3000|3001|3002|3004|3010|8888|8090)'
Rebuild + restart a Next.js preview frontend
# Pattern: cd into source, do a one-shot build inside an ephemeral node container,
# then restart the long-running container.
# Replace PORT and NAME / SITE_URL as needed for the target frontend.

cd /opt/fxn-cms-git/backend/nxtsmart-homes   # or nxt-bargains, bestlooking-skin, originfacts-com

docker run --rm --network fxnstudio-cms_fxn-net -v "$PWD":/app -w /app \
  -e NEXT_PUBLIC_SITE_URL=https://nxtsmarthomes.fxnstudio.com \
  -e NEXT_PUBLIC_STRAPI_URL=https://cms.fxnstudio.com \
  node:20-alpine sh -c "corepack enable && yarn install --frozen-lockfile && yarn build"

docker restart nxtsmart-homes

# Verify
curl -sI -o /dev/null -w "https=%{http_code}\n" https://nxtsmarthomes.fxnstudio.com/
Pull from git and rebuild (deploy)
# Example for nxtsmart-homes — same shape for the others
cd /opt/fxn-cms-git/backend/nxtsmart-homes
git pull --ff-only

docker run --rm --network fxnstudio-cms_fxn-net -v "$PWD":/app -w /app \
  -e NEXT_PUBLIC_SITE_URL=https://nxtsmarthomes.fxnstudio.com \
  -e NEXT_PUBLIC_STRAPI_URL=https://cms.fxnstudio.com \
  node:20-alpine sh -c "yarn install --frozen-lockfile && yarn build"

docker restart nxtsmart-homes

# For bestlooking.skin prod (when re-enabled) see the canonical script:
# /opt/fxn-cms-git/backend/deploy-bestlooking-skin.sh
Strapi: rebuild the image after schema/code changes
# Required whenever you change /opt/fxn-cms-git/backend/strapi-deploy/strapi/src/**
# (e.g. new content types, bootstrap, lifecycles)

cd /opt/fxn-cms-git/backend/strapi-deploy
docker compose build strapi
docker compose up -d strapi

# Wait for ready
until curl -sf http://127.0.0.1:8888/_health; do sleep 2; done; echo ' OK'
Strapi: restart without rebuild (config/env-only changes)
cd /opt/fxn-cms-git/backend/strapi-deploy
docker compose restart strapi
docker logs --tail 50 fxn-strapi
Re-run the WP → Strapi importer (nxtsmart.homes)
# Idempotent (legacyWpId-keyed). Re-running updates existing posts and
# backfills publishedAt from WP date_gmt via a single SQL UPDATE.

STRAPI_API_TOKEN=<token> \
  python3 /opt/fxn-cms-git/backend/scripts/import-wp-to-nxtsmart.py

# Useful flags
#   --limit 5            # only the first N posts
#   --categories-only    # skip posts
#   --posts-only         # skip categories (after first run)
#   --dry-run            # print actions, write nothing
nginx: reload after editing a vhost
# Edit a config under /etc/nginx/sites-available/ , then:
nginx -t           # validate
systemctl reload nginx

# Enable / disable a site
ln -s /etc/nginx/sites-available/<name> /etc/nginx/sites-enabled/<name>
rm    /etc/nginx/sites-enabled/<name>
Let's Encrypt: issue a cert for a new subdomain
# DNS must point to this server first.
certbot certonly --nginx -d <subdomain.fxnstudio.com> \
  --non-interactive --agree-tos -m kritin@fxnholdings.com

# List + manual renew check
certbot certificates
certbot renew --dry-run
Cleanup: stopped containers, dangling images, old build cache
# Safe — only removes stopped containers and dangling layers
docker container prune -f
docker image prune -f

# Aggressive — also removes UNUSED images (anything not attached to a container)
docker system prune -af