OrbitPage is an open-source public page manager you can run on your own server. It gives you one polished place for links, text blocks, social destinations, venue details, campaigns, announcements, click analytics, privacy controls, backup/restore, and production-ready Docker images without requiring an external database.
Most public-page tools are either hosted SaaS products or self-hosted projects that need extra services before you can get started. OrbitPage is built for anyone who wants a clean public page and an admin experience that still feels simple when it runs on their own infrastructure.
| If you want... | OrbitPage gives you... |
|---|---|
| A flexible public page | Links, text cards, separators, social links, avatars, cover images, venue or brand details, and SEO metadata |
| A self-hosted setup | Docker, SQLite, local uploads, health checks, and a single persistent data volume |
| Control over privacy | Optional analytics, consent/legal settings, no required external database, and self-owned data |
| A usable admin panel | Live preview, drag-and-drop ordering, theme editing, scheduling, access management, and inline feedback |
| Safer operations | JWT auth, bcrypt passwords, upload restrictions, storage quotas, backup/restore, CI, and Docker smoke tests |
- Why OrbitPage?
- Try the Demo
- Features
- Screenshots
- Quick Start with Docker
- Quick Start
- Production Notes
- Deploy Anywhere
- Configuration
- Development
- Search and Sharing
- Documentation
- Changelog
- License
The demo is the fastest way to see both sides of OrbitPage: the public page visitors see, and the admin panel you use to manage it.
| Area | Link | Login |
|---|---|---|
| Public page | orbitpage-demo.paoloronco.it | No login required |
| About OrbitPage | orbitpage-demo.paoloronco.it/about | No login required |
| Admin panel | orbitpage-demo.paoloronco.it/admin | admin / ChangeMe123! |
Demo changes may be reset and should not be used for private data.
| Area | Highlights |
|---|---|
| Public page | Name/brand, avatar or logo, bio/description, social links, link cards, text cards, separators, cover images, SEO metadata, legal footer links |
| Link management | Link/text/separator blocks, visibility toggles, scheduling, drag-and-drop ordering, JSON import/export |
| Design | Theme editor, live preview, colors, gradients, typography, spacing, radius, blur, glow, custom CSS |
| Admin | Page editor, analytics, privacy/legal settings, access management, password management, demo mode support |
| Data ownership | SQLite persistence, local uploads, full JSON backup/restore, Docker volume support |
| Security | bcrypt password hashing, signed JWT sessions, encrypted browser token storage, rate limits, upload restrictions, storage quota |
| Deployment | Docker Hub, GHCR, Docker Compose, health endpoint, Cloud Run compatible, no external database required |
| Public page | Admin links |
|---|---|
![]() |
![]() |
| Theme editor | Page editor |
|---|---|
![]() |
![]() |
Walkthroughs:
Docker is the recommended way to run OrbitPage in production or on a home server.
docker run -d --name orbitpage \
-p 8080:8080 \
-e NODE_ENV=production \
-e PORT=8080 \
-e JWT_SECRET="$(openssl rand -hex 32)" \
-v orbitpage_data:/app/data \
paueron/orbitpage:latestOpen:
- Public page: http://localhost:8080
- Admin panel: http://localhost:8080/admin
The first admin visit asks you to create the admin password. The first username is always admin.
Use this path when you want to run OrbitPage from source.
git clone https://github.com/paoloronco/OrbitPage.git
cd OrbitPage/app
npm ci
npm run install:server
npm run startOpen:
- Public page: http://localhost:3001
- Admin panel: http://localhost:3001/admin
- Health check: http://localhost:3001/health
On the first admin visit, OrbitPage asks you to create the admin password. The first username is always admin.
Requirements:
- Node.js
^20.19.0or>=22.12.0 - npm
- Git
The same image is published to Docker Hub and GitHub Container Registry.
Docker Hub:
paueron/orbitpage:latestGHCR:
ghcr.io/paoloronco/orbitpage:latestThe /app/data volume stores the SQLite database and uploads. Keep it mounted before upgrading or recreating the container.
docker compose up -dBefore exposing the app publicly, replace the sample JWT_SECRET in docker-compose.yml.
OrbitPage can run on any platform that supports a Docker container or a Node.js service: Cloud Run, Render, Fly.io, DigitalOcean App Platform, Azure App Service, Koyeb, Northflank, CapRover, Dokku, Coolify, and similar providers.
For container platforms, the deployment shape is always the same:
NODE_ENV=production
PORT=8080
JWT_SECRET=replace-with-a-long-random-secretThen persist /app/data and expose port 8080. Most platforms provide HTTPS at the edge, so ENABLE_HTTPS is usually only useful for local or private self-signed deployments.
The production essentials are intentionally small:
| Variable | Required | Purpose |
|---|---|---|
JWT_SECRET |
Yes in Docker/production | Stable signing key for admin sessions. Use a long random value. |
PORT |
Usually | HTTP port. Docker defaults to 8080; local Node defaults to 3001. |
DATA_DIR |
Recommended for custom installs | Directory for orbitpage.db and uploads. Docker uses /app/data. |
UPLOAD_STORAGE_QUOTA_MB |
Optional | Maximum total upload storage in MB. Defaults to 1024. |
PUBLIC_SITE_URL |
Recommended behind proxies | Canonical public URL for SEO, sitemap, and social previews. |
SEO_INDEXING |
Optional | Set to false for staging/private deployments. |
RESET_TOKEN |
Optional | Enables protected recovery/reset endpoints. Use at least 32 characters. |
See the full environment reference in docs/wiki/Configuration.md.
Development mode uses two processes: Express for the API and Vite for the frontend.
cd OrbitPage/app
npm ci
npm run install:serverTerminal 1:
npm run server:devTerminal 2:
npm run devOpen:
- Frontend: http://localhost:8080
- Admin panel: http://localhost:8080/admin
- API health check: http://localhost:3001/health
Useful checks:
npm run lint
npm run test:unit
npm run buildOrbitPage generates metadata from your saved public page and environment, so most deployments do not need source-code SEO edits.
Recommended production values:
PUBLIC_SITE_URL=https://links.example.com
PUBLIC_SITE_NAME="Your Name or Brand"
SEO_INDEXING=trueUse SEO_INDEXING=false for private, staging, or preview deployments. OrbitPage will emit noindex metadata and a blocking robots.txt.
OrbitPage also serves:
- page-based title and meta description
- canonical URL
- Open Graph and Twitter Card metadata
- Schema.org JSON-LD
- dynamic
robots.txt - dynamic
sitemap.xmlwith automaticlastmodupdates from public content changes - editable
llms.txtplusllm.txtalias - editable
humans.txt,ai.txt, andsecurity.txt noindexheaders for admin, API, health, and unknown SPA routes
Admins can edit these TXT endpoints from the Privacy/TXT area. Demo deployments expose the files but keep editing disabled.
Full guidance lives in docs/wiki/SEO-and-indexing.md.
The README is the quick path. Longer operational docs live in docs/wiki/ and are ready to mirror into the GitHub Wiki:
Show full changelog
v4.6.0
- Accepts and persists the new profile-card and content-card palette objects in the theme API.
- Restores saving for ready-made themes, card styles, imports, and manual fine tuning.
- Adds backend regression coverage for modern nested theme payloads.
v4.4.0
- Expands the block system with headings, images, contacts, social rows, callouts, maps, events, and consent-aware embeds.
- Adds independent ready-made page themes and card-style presets with live previews and unrestricted fine tuning.
- Adds complete profile-card and avatar customization, including colors, borders, accents, and image shape.
- Aligns Admin previews with public rendering and reorganizes the Links editor into clear content, publishing, media, and appearance sections.
- Hardens Google Analytics Consent Mode v2 and external CMP integrations for Cookiebot, CookieYes, OneTrust, iubenda, and custom providers.
- Adds secure embed sandboxing, stricter CSP provider allowlists, and expanded CMP regression coverage.
v4.3.28
- Updates
/sitemap.xmlautomatically from public content timestamps. - Uses profile, links, theme, consent, and TXT file changes to generate stable
lastmodvalues. - Serves the sitemap with no-store headers so crawlers do not keep stale XML.
v4.3.27
- Adds dynamic
robots.txt,llms.txt,llm.txt,humans.txt,ai.txt, andsecurity.txtendpoints. - Adds an admin TXT editor with save/reset controls and demo-mode read-only protection.
- Persists custom TXT files in SQLite and includes them in backup/restore.
v4.3.26
- Adds richer server-rendered SEO metadata for the demo
/aboutpage. - Adds Open Graph/Twitter image metadata and SoftwareApplication JSON-LD for better social previews and search snippets.
- Covers the About SEO metadata with backend regression tests.
v4.3.25
- Adds a polished
/aboutpage for the public demo instance. - Keeps
/aboutunavailable outside demo mode and links it from the README demo table.
v4.3.24
- Moves the Docker quick start directly above the source quick start.
- Keeps the README contents order aligned with the rendered section order.
v4.3.23
- Reworks the GitHub README around self-hosted public page positioning.
- Adds clearer demo, Docker quick start, feature, screenshot, and deployment sections.
v4.3.22
- Adds explicit read-only
GITHUB_TOKENpermissions to CI and Gitea mirror workflows. - Covers the workflow permission policy with deployment configuration tests.
v4.3.21
- Builds the frontend before running server tests in GitHub Actions.
- Locks the workflow order so SPA and SEO tests always have
dist/index.htmlon clean runners.
v4.3.20
- Moves auth and user-management request validation into a dedicated Zod schema module.
- Replaces duplicated manual checks in setup, login, user, role, password, and reset handlers.
v4.3.19
- Adds admin dashboard controls to download a full backup JSON.
- Adds guarded restore from backup with inline success and error states.
v4.3.18
- Adds admin-only backup export for application tables and upload files.
- Adds restore support with safe upload path validation and transactional database writes.
v4.3.17
- Adds a configurable
UPLOAD_STORAGE_QUOTA_MBlimit for files stored inuploads. - Removes the newly uploaded file and returns
413when the quota is exceeded.
v4.3.16
- Generates upload filenames with UUIDs instead of predictable random suffixes.
- Stores uploaded media with owner-writable, non-world-writable permissions.
- Copies extracted backend service modules into the production Docker image.
v4.3.15
- Aligns client-side avatar, icon, and cover image uploads with the backend raster-image policy.
- Rejects unsanitized SVG files before they can be converted into stored data URLs.
v4.3.14
- Adds a shared frontend link DTO normalizer backed by Zod.
- Replaces duplicated link mapping in Admin and public page loading, reducing lint warnings from 154 to 114.
v4.3.13
- Moves consent configuration validation schemas into a dedicated backend schema module.
- Adds regression coverage for consent config defaults and supported CMP providers.
v4.3.12
- Extracts backend link validation schemas from the server monolith into a dedicated module.
- Keeps the production Docker image aware of extracted server modules.
v4.3.11
- Adds blocking dependency audits for frontend and backend packages in GitHub Actions.
- Adds a Docker smoke test that builds the production image, starts it with a CI secret, and checks
/health.
v4.3.10
- Makes theme import, reset, and editing follow the same preview-then-save workflow.
- Exports the pending theme and keeps unsaved theme changes visible when saving fails.
v4.3.9
- Keeps unsaved link changes visible when saving fails instead of clearing the dirty state too early.
- Shows the save error inline in the link manager so admins can retry without losing context.
v4.3.8
- Treat bootstrap CMP states from Cookiebot, OneTrust, and Cookiebot events as implicit until a user action is explicitly detected, preventing pre-granted consent from loading Google Analytics too early.
- Improve Google Consent Mode propagation from builder CMPs and keep script dispatch aligned with explicit consent only.
- Ensure the CCPA "Do not sell my personal information" footer link remains available with locale-aware label variants and a stable fallback target.
v4.3.6
- Distinguishes implicit consent state from explicit user consent for all supported external CMPs (iubenda, Cookiebot, CookieYes, OneTrust, custom snippets).
- Defers third-party tag loading until consent is explicitly granted, including GA4 script/config gating and Google Consent Mode updates.
- Syncs Google Consent Mode updates even when
gtagis not yet loaded, avoiding silent failures and premature network requests. - Restores privacy footer policy URL resolution from
consentConfig.legalPolicies, so CCPA "Do not sell my personal information" links remain available when hosted/embedded legal pages are used.
v4.3.6
- Prevents builder-mode external CMP signals (especially iubenda) from being treated as explicit consent before user interaction.
- Separates implicit provider state from explicit consent, so
gtag('consent', 'update')and consent-dependent scripts dispatch only after explicit choice. - Restricts dataLayer fallback sync to
consent updateentries only, preventing default/implicit consent bootstrap from firing tags early.
v4.3.5
- Reworks the README around demo-first evaluation, shorter feature scanning, Docker production setup, configuration, development, and SEO basics.
- Adds a wiki-ready documentation set with expanded deployment, configuration, development, SEO, security, and troubleshooting guides.
- Updates
SECURITY.md,CONTRIBUTING.md, and the Docker Compose image reference to match the current app architecture.
v4.3.4
- Fixes the main-branch Docker workflow so
X.Xtags are computed without shell-interpreted JavaScript template literals. - Adds regression coverage to keep version and minor-version image tags published from the package version.
- Keeps Docker Hub and GHCR publishing aligned for
latest,X.X.X,vX.X.X, andX.Xtags.
v4.3.3
- Publishes Docker version tags directly from the main-branch build, including
X.X.X,vX.X.X, andX.X. - Avoids relying on tag-triggered workflows for automated release tags created by GitHub Actions.
- Keeps Docker Hub and GHCR tags aligned from the same build output.
v4.3.2
- Publishes Docker images to both Docker Hub (
paueron/orbitpage) and GitHub Container Registry (ghcr.io/paoloronco/orbitpage). - Keeps
latest, semantic version, minor version, and short SHA tags aligned across both registries. - Documents the GHCR pull path alongside the existing Docker Hub distribution path.
v4.3.1
- Aligns both Dockerfiles on the production runtime contract: Node 22,
PORT=8080,DATA_DIR=/app/data, and mandatoryJWT_SECRET. - Makes the
app/Dockerfile self-contained fordocker build ./app. - Avoids the expected unauthenticated
/api/auth/verifycall when opening the admin login page without a stored token.
v4.3.0
- Renames the Security admin tab to Access.
- Adds full multi-user management: list users, create users, change any user's password, and delete users.
- The
adminuser is created by default and cannot be deleted. - Login form now accepts any username; backend validates credentials per-user.
POST /api/auth/change-passwordnow changes the password of the currently authenticated user (not hardcoded toadmin).- New API endpoints:
GET /api/users,POST /api/users,PUT /api/users/:username,DELETE /api/users/:username.
v4.2.0
- Adds optional cover/header image to link and text cards.
- Full-bleed 16:9 image displayed at the top of each card on both the public page and admin panel.
- Supports URL input or local file upload; alt text field for accessibility.
- Graceful fallback on broken image (no layout shift).
- DB migrations for
cover_imageandcover_image_altcolumns (additive, non-destructive).
v4.1.8
- Allows the current Usercentrics embed domains in the production CSP.
- Keeps embedded legal policy scripts executable and ordered when rendered on
/privacyand/cookies. - Adds a regression test for legal policy provider CSP sources.
v4.1.7
- Executes custom external CMP scripts reliably, including pasted iubenda widget snippets.
- Publishes Docker images only from release tags to avoid duplicate Docker builds on
mainandv*. - Keeps
latest, semantic version, and short SHA Docker tags on release builds.
v4.1.6
- Adds a server-side demo preset for Privacy Policy, Cookie Policy, and external CMP.
- Serves the demo legal pages from the requested iubenda embeds when
DEMO_MODE=true. - Keeps public footer links on
/privacyand/cookiesin demo mode. - Ensures iubenda embedded policy scripts load reliably in SPA-rendered legal pages.
v4.1.5
- Stops demo-mode write protection from being shown as an expired admin session.
- Ensures embedded legal policy scripts execute on
/privacyand/cookies. - Infers hosted legal pages from existing
/privacyand/cookiesprofile URLs for upgraded installs.
v4.1.4
- Separates legal pages from consent management in the Privacy tab.
- Adds provider-agnostic legal policy sources: external link, hosted text, and embedded code.
- Replaces provider-specific CMP fields with a single external script flow.
- Ensures
/privacyand/cookiesalways render the latest selected source without stale provider fallback. - Keeps form edits on screen when the admin session expires during save.
v4.1.3
- Ensures Google Consent Mode v2 defaults are set before analytics scripts load.
- Defaults ad storage, analytics storage, user data, and personalization to denied when consent is enabled.
- Avoids duplicate default consent blocks when an advanced provider already supplies one.
v4.1.2
- Redesigned the Privacy tab legal policy setup with a guided, non-technical flow.
- Added a footer visibility toggle, configured/missing status, and preview links for
/privacyand/cookies. - Added a public
/cookiesplaceholder page.
v4.1.1
- Moved Privacy Policy and Cookie Policy editing from the page editor to Privacy.
- Kept the existing profile-backed fields as the single persistence source.
- Forced the public
/privacypage to render in a readable light layout.
v4.1.0
- Made Admin > Page > Legal links the single editable source for Privacy Policy and Cookie Policy URLs.
- Shows configured legal links in the public footer and hides them cleanly when empty.
- Makes the Privacy & Cookies tab read-only for policy URLs, with an Edit in Page shortcut.
- Ensures the native cookie banner derives policy URLs from the profile instead of storing duplicate consent-config URLs.
v4.0.0
- Redesigned the Admin panel with a clearer dashboard layout, status metrics, sticky centered navigation, and a lighter operational workspace.
- Improved the Links editor with a clearer toolbar, content creation cards, save state visibility, and a more helpful empty state.
- Added animated profile checklist guidance and save confirmation feedback for theme changes.
- Kept the public page preview isolated from the Admin styling so it continues to reflect the saved public theme.
- Added a single public-page payload endpoint to load profile, links, and theme together and avoid flashes of default content.
- Preserved compatibility with existing SQLite databases through additive migrations only.
v3.8.0
- Added Google Analytics 4 integration in the Admin panel (new Integrations tab).
- The GA4 Measurement ID (
G-XXXXXXXXXX) is stored in the database and injected as agtag.jsscript on the public page only — the admin panel is never tracked. - Content Security Policy updated to allow
googletagmanager.comandgoogle-analytics.comscript and connect sources. - Measurement ID is validated client-side before saving (format
G-XXXXXXXXXX).
v3.7.0
- Fixed production blank page behavior caused by CORS/CSP headers blocking API calls in production containers.
- Fixed stale frontend assets in Docker builds by cleaning
distbefore building. - Fixed legacy database migration handling.
- Fixed missing
fsimport indatabase.js.
- Improved production CORS handling for same-origin and reverse-proxy deployments.
- Refined Content Security Policy settings.
- Added static asset serving logs for deployment troubleshooting.
- Improved database migration validation and error handling.
v3.6.0
- Added live preview inside the admin panel.
- Added a View Public Page action from the admin header.
- Added link visibility toggles.
- Added mobile drag-and-drop ordering.
- Removed sensitive authentication logs.
- Removed unused Supabase and Firebase code.
- Fixed duplicate database migration logic.
- Removed debug logging from
PublicLinkCard.
v3.5.1
- Updated vulnerable frontend, backend, and Docker dependencies.
- Resolved Dependabot alerts and Docker image CVEs reported at the time of release.
- Optimized Docker build time by avoiding source builds where precompiled binaries are available.
v3.5.0
- Added editable profile fields with line-break support in the bio.
- Added social link controls and profile picture display controls.
- Added text cards and bulleted lists.
- Added JSON import/export for links and themes.
- Added theme controls for page styling, typography, title, meta description, and footer text.
- Added Docker startup validation for
JWT_SECRET. - Added optional self-signed HTTPS support with
ENABLE_HTTPS=true.
MIT License. See LICENSE.txt.



