Standard
Document Type: Backend Infrastructure Standards Document
Project: Just Headlines
Applies To: Local development, local previews, Cloudflare Tunnel origin mappings, internal admin portal development, public site preview, SaaS application services, future internal tools, future AI-agent services, and future local service expansion.
Status: Authoritative project standard unless later superseded by a newer dated standards document.
Primary Purpose: Define how Just Headlines assigns local server ports so that local development, Cloudflare Tunnel configuration, internal tooling, AI-agent automation, and future service expansion remain organized, predictable, and easy to maintain.
1. Purpose of This Standard
This document defines the Just Headlines local server port allocation standard.
This document also defines how the local port standard relates to the current Cloudflare Tunnel implementation. The local server addresses remain the origin addresses for the running services. The Cloudflare Tunnel URLs are now the approved authenticated browser-access routes for reaching the current local public site preview and current private admin portal from devices that are not the server machine.
The current tunnel-mapped local services are:
Public site local origin: http://127.0.0.1:43000/
Public site tunnel URL: https://jh-site.darkhorsekarma.net/
Admin portal local origin: http://127.0.0.1:42000/
Admin portal tunnel URL: https://jh-admin.darkhorsekarma.net/
The Cloudflare Tunnel URLs do not replace the local port assignments. They extend the access model by giving approved users an authenticated browser route to selected local services while the services continue to bind to 127.0.0.1 on the server machine.
The purpose of this standard is not to create security through secrecy. The purpose is to create a durable internal organization convention for assigning local server ports in a way that is predictable, scalable, easy to document, easy for humans to understand, and easy for AI agents and automation tools to follow.
As the project grows, more local services will exist. Some will be static local previews. Some will be internal web tools. Some will be dashboards. Some will be application services. Some will be API mock servers. Some will be future AI-agent work surfaces. Some may be reverse proxies or local gateways. Some may be temporary development servers. Without a standard, port assignments can become arbitrary and difficult to reason about. Random port assignment creates avoidable confusion, increases the chance of collisions, and makes future migration or refactoring harder.
This standard creates a clean allocation model using local port blocks in the 41000–45999 range.
The major project areas receive their own 1,000-port blocks:
41000–41999 app / SaaS core
42000–42999 admin / private company access portal
43000–43999 site / public customer website
44000–44999 shared local infrastructure
45000–45999 experiments / temporary development
The first port in each block, ending in 000, is reserved as the main local gateway or primary local preview port for that project area.
The remaining ports in that block, ending in 001 through 999, are available for related subservices, future tools, internal previews, development servers, dashboards, API mocks, temporary services, and route-specific helpers associated with that project area.
Example concept:
42XXX block = admin/private company access portal block
42000 = main admin gateway or primary admin portal preview
42001–42999 = assignable admin-related subservice ports
This is a standard for local host and local server organization. It should guide how Cloudflare Tunnel origin mappings are planned, but the port numbers themselves are not the security boundary.
2. Core Rule
The core rule is:
Each major project area receives a dedicated 1,000-port block. The
4X000port is the main local gateway or primary local preview for that area. Ports4X001–4X999remain available for related subservices.
The blocks are:
41000–41999 app / SaaS core
42000–42999 admin / private company access portal
43000–43999 site / public customer website
44000–44999 shared local infrastructure
45000–45999 experiments / temporary development
This rule means that when a human operator, developer, Codex session, AI agent, automation script, or future MCP-connected tool sees a local port, the port itself provides immediate context.
A service using a port in the 41000 range is related to the SaaS application core.
A service using a port in the 42000 range is related to the admin/private company access portal.
A service using a port in the 43000 range is related to the public customer-facing site.
A service using a port in the 44000 range is shared infrastructure.
A service using a port in the 45000 range is experimental, temporary, or disposable unless formally promoted into one of the permanent blocks.
This convention reduces ambiguity.
3. Security Context
This standard intentionally uses non-default local ports, but non-default ports must not be treated as the main security control.
Using a non-default port can reduce accidental conflicts and makes the local development environment more organized. It can also avoid common assumptions made by generic tools that expect development servers on ports such as 3000, 5000, 5173, 8000, 8080, 8100, or 8888.
However, non-default ports are not a substitute for real security.
The actual security model for private services must come from:
- Binding local development servers to
127.0.0.1rather than0.0.0.0. - Avoiding inbound router port forwarding.
- Using Cloudflare Tunnel for outbound-only exposure where remote access is required.
- Protecting private hostnames with Cloudflare Access or an equivalent identity-aware access layer.
- Maintaining default-deny access policies for private/admin services.
- Avoiding
Bypass: Everyoneor equivalent public bypass rules on private services. - Separating public, admin, app, and shared services by hostname, repo, and access policy where applicable.
- Avoiding secrets in repositories.
- Avoiding direct exposure of internal control surfaces.
- Using explicit authentication and authorization on dangerous admin operations.
The local port number is an organizational convention. It is not a firewall. It is not an access-control policy. It is not a replacement for Cloudflare Access, authentication, proper binding, network isolation, or careful service design.
A local service bound only to 127.0.0.1 is not directly scannable from the public internet. When a Cloudflare Tunnel maps a public hostname to a local service, the public hostname is what external users and attackers see. They do not see the local port number directly. Therefore, the choice of local port is mostly for human and machine organization, not external obscurity.
That said, using a clear non-default port convention is still useful because it prevents the project from becoming dependent on common defaults and reduces future confusion.
4. Localhost and Binding Rules
All local services covered by this standard should bind to:
127.0.0.1
unless there is a specific documented reason to bind to a different local interface.
Use:
127.0.0.1
Do not use:
0.0.0.0
unless the service is deliberately intended to listen on all network interfaces and the risk has been reviewed.
Do not use:
127.0.0.0
127.0.0.0 is not the normal loopback host address for local development. Use 127.0.0.1.
Recommended local preview form:
http://127.0.0.1:43000/
The word localhost may work, but 127.0.0.1 is more explicit. For standards documentation, scripts, and tunnel origin configuration, prefer 127.0.0.1.
When Cloudflare Tunnel is configured for a local service, the 127.0.0.1 address remains the server-local origin address. It should still be used for direct checks on the server machine, local process validation, service startup testing, and tunnel origin configuration.
The matching Cloudflare Tunnel URL is the browser-facing access address. It should be used when the same service needs to be reached from another computer, a phone, a tablet, an incognito browser session, a contractor device, an employee device, an AI-agent browser workflow, or any other device that reaches the service through the internet rather than through the server machine itself.
For the current assigned gateway ports, the distinction is:
http://127.0.0.1:43000/ server-local public site preview
https://jh-site.darkhorsekarma.net/ authenticated tunnel access to the same public site preview
http://127.0.0.1:42000/ server-local private admin portal
https://jh-admin.darkhorsekarma.net/ authenticated tunnel access to the same private admin portal
5. Why Use the 41000–45999 Range
The selected range sits within the user/registered port range and avoids common development defaults.
General port ranges are:
0–1023 System / well-known ports
1024–49151 User / registered ports
49152–65535 Dynamic / ephemeral ports
This standard avoids:
- The well-known system range, because those ports are associated with standard system services and often require elevated privileges.
- The dynamic/ephemeral range, because the operating system may temporarily claim ports in that range for outbound connections.
- Common development defaults, because those are often already used by frameworks or assumed by tutorials.
The 41000–45999 range provides a large, easy-to-remember block that is still below the dynamic/ephemeral range.
This gives Just Headlines room to grow without needing random port decisions later.
6. The Project Port Blocks
The following blocks are reserved by this standard.
6.1 App / SaaS Core Block
41000–41999
This block belongs to the core SaaS application repository.
The repository is currently named news and is expected to be renamed to app later. This block should be understood as the application/backend block regardless of the current repository name.
This block is for services related to:
- SaaS core application behavior
- feed processor status interfaces
- ingestion status interfaces
- worker status services
- subscriber/account service interfaces
- Telegram access logic interfaces
- local application APIs
- backend administrative APIs
- local database viewers related to the SaaS application
- controlled internal app services
- backend service previews
- app-specific test servers
The main app gateway or primary app local service should use:
41000
The assignable app subservice range is:
41001–41999
6.2 Admin / Private Company Access Portal Block
42000–42999
This block belongs to the admin repository.
The admin repository is the private company access portal for operator, employee, and AI-agent workflows. It is not customer-facing. It should host or support internal dashboards, internal documents, reports, tools, status pages, logs, AI-agent surfaces, internal links, and future protected administrative interfaces.
This block is for services related to:
- admin portal gateway
- internal document library
- internal dashboards
- internal reports
- internal tools
- system status views
- log viewers
- AI-agent work surfaces
- internal command center pages
- admin-only previews
- private local services used by the admin portal
The main admin gateway or primary admin portal local service should use:
42000
The assignable admin subservice range is:
42001–42999
6.3 Site / Public Customer Website Block
43000–43999
This block belongs to the site repository.
The site repository is the public customer-facing website. Anything in the site repository either is directly visible to customers or directly affects what customers see.
This block is for services related to:
- public site preview
- customer-facing documentation preview
- customer account/dashboard UI preview
- public static preview servers
- public site build previews
- public-facing API mocks used only for site development
- public website testing tools
- public page preview helpers
The main public site local preview should use:
43000
The assignable public site subservice range is:
43001–43999
In ordinary use, the public documentation library does not need its own port. If the public site is served at 127.0.0.1:43000, the public documents can usually be reached through a route such as:
http://127.0.0.1:43000/docs/
A separate documents preview port inside the 43000 block should only be assigned if the documentation system needs to be served independently from the full public site preview.
6.4 Shared Local Infrastructure Block
44000–44999
This block is reserved for shared local infrastructure that does not belong exclusively to app, admin, or site.
This block may be used for:
- local reverse proxies
- shared development gateways
- local test identity providers
- local mock infrastructure
- shared monitoring views
- shared local utility servers
- cross-repository helper services
- shared MCP servers
- local agent orchestration services
- shared webhooks for local testing
- local infrastructure dashboards
This block should not be used casually. If a service clearly belongs to app, admin, or site, use that project block instead.
The main shared infrastructure gateway, if one is created, should use:
44000
The assignable shared infrastructure subservice range is:
44001–44999
6.5 Experiments / Temporary Development Block
45000–45999
This block is reserved for experiments, prototypes, temporary demos, short-lived test servers, and development work that has not yet been assigned to a permanent project block.
This block may be used for:
- temporary test servers
- throwaway prototypes
- framework experiments
- proof-of-concept dashboards
- experimental AI-agent tools
- short-lived service demos
- temporary local tunnels for testing
- one-off debugging interfaces
A service should not remain in the 45000–45999 block indefinitely if it becomes part of the durable architecture.
If an experiment becomes a real app, admin, site, or shared infrastructure service, it should be moved into the appropriate permanent block and documented there.
7. Meaning of the 4X000 Gateway Port
The first port in each 1,000-port block is reserved as the main local gateway or primary local preview for that project area.
The pattern is:
4X000 = main gateway / primary preview for the block
4X001–4X999 = related subservices for the block
For example:
42000 = main admin gateway / primary admin portal
42001–42999 = admin-related subservices
The gateway port is the port that should normally be mapped to the primary public or private hostname through Cloudflare Tunnel.
Conceptually:
admin hostname → Cloudflare Tunnel → 127.0.0.1:42000
The gateway may serve static files directly, or it may act as a local reverse proxy that routes subpaths to other local services.
For example, an admin gateway could serve the admin home page and route internal paths to separate local services:
/admin home page served by gateway
/documents/ served by static files or document build output
/dashboards/ proxied to a dashboard service
/tools/ proxied to an internal tools service
/status/ proxied to a status service
The exact implementation may vary, but the standard is that the main entry point for a block uses the 4X000 port.
8. Meaning of the 4X001–4X999 Subservice Range
The remaining 999 ports in each block are reserved for related subservices.
A subservice is any local service that belongs to the same project area but is not the main gateway.
Subservices may include:
- a React development server
- a static preview server
- a dashboard application
- a log viewer
- a status viewer
- a reports viewer
- an API mock
- a local tool service
- a worker status endpoint
- a local webhook receiver
- a database viewer
- an AI-agent work surface
- a temporary service under active development
These ports should be assigned deliberately and documented.
The subservice range provides room for future expansion without requiring a new port scheme.
The important rule is that a subservice should stay inside the block of the project area it belongs to.
If a service exists only for the admin portal, it should use the 42000 block.
If a service exists only for the public customer site, it should use the 43000 block.
If a service exists only for the SaaS application backend, it should use the 41000 block.
If a service is shared across multiple repos or project areas, it may belong in the 44000 block.
If the service is temporary, experimental, or not yet assigned, it may belong in the 45000 block.
9. Examples Are Not Assignments
Examples in this document are examples only unless explicitly marked as assigned.
Future humans, Codex sessions, ChatGPT sessions, AI agents, MCP-connected tools, and automation scripts must not treat example port numbers as production assignments unless those assignments are listed in a formal port registry or a later implementation document.
The purpose of examples is to show how the standard can be applied.
Example language should be interpreted as conceptual unless it appears in a registry section with a status such as:
Assigned
Reserved
Deprecated
Retired
This distinction matters because future services may be organized differently than the examples.
The standard is the block allocation and the gateway/subservice pattern, not every sample number shown in the document.
10. Conceptual Example: Main Gateway and Subservices
This example illustrates the model.
Assume a project area has a block:
4X000–4X999
The main gateway uses:
4X000
Related subservices may use:
4X001
4X002
4X003
...
4X999
A browser or Cloudflare Tunnel may route to the gateway, and the gateway may route internally to subservices.
Conceptual flow:
public or private hostname
↓
Cloudflare Tunnel
↓
127.0.0.1:4X000
↓
local gateway
↓
subpaths or internal routes
↓
127.0.0.1:4X001, 4X002, 4X003, etc.
This allows a human to remember one primary URL while the internal architecture can still use multiple local services.
11. Conceptual Example: Single-Port Static Site
A static website may need only one port.
For example, if a public site is served from one static output directory, the primary local preview port can serve all routes:
http://127.0.0.1:4X000/
http://127.0.0.1:4X000/docs/
http://127.0.0.1:4X000/account/
In this case, separate subservice ports are unnecessary.
Do not create extra ports merely because a site has multiple URL paths.
A path is not the same thing as a service.
A service needs its own port only when it runs as its own local server, development server, reverse-proxied app, separate backend, separate dashboard process, or independently hosted preview.
12. Conceptual Example: Gateway With Internal Apps
A more complex internal portal may use one primary gateway and several internal subservices.
Conceptual example only:
127.0.0.1:4X000 main portal gateway
127.0.0.1:4X001 document library preview
127.0.0.1:4X002 dashboard development server
127.0.0.1:4X003 reports development server
127.0.0.1:4X004 internal tools service
The human operator may only visit:
https://private-hostname.example/
or locally:
http://127.0.0.1:4X000/
The gateway then routes internal paths to the appropriate services.
This is useful when different parts of the portal are built with different technologies.
However, if all sections are static files served by the same server, the extra ports are unnecessary.
13. Path Versus Port
A path and a port are different things.
A path is part of a URL served by a web server:
/documents/
/reports/
/dashboards/
/tools/
A port identifies the local service receiving the HTTP request:
127.0.0.1:42000
If one local server can serve all paths, one port is enough.
If different applications run as separate local servers, each application generally needs its own port.
The gateway pattern allows both:
Human-facing path:
https://admin-hostname.example/dashboards/
Internal routing:
127.0.0.1:42000 receives the request
gateway routes /dashboards/ to a dashboard service if needed
This keeps the user experience simple while allowing the backend implementation to grow.
14. Cloudflare Tunnel Planning
Cloudflare Tunnel origin mappings should use the assigned local gateway ports where possible.
The gateway-port rule is still the correct planning model because a Cloudflare Tunnel route needs a stable local origin. The tunnel hostname is the browser-facing address. The 127.0.0.1 address and assigned port are the local origin reached by the cloudflared connector on the server machine.
Conceptual mappings:
app hostname → 127.0.0.1:41000
admin hostname → 127.0.0.1:42000
site hostname → 127.0.0.1:43000
Current active mappings:
https://jh-site.darkhorsekarma.net/
↓
Cloudflare Access
↓
Cloudflare Tunnel
↓
cloudflared connector on the server machine
↓
http://127.0.0.1:43000/
↓
public site preview
https://jh-admin.darkhorsekarma.net/
↓
Cloudflare Access
↓
Cloudflare Tunnel
↓
cloudflared connector on the server machine
↓
http://127.0.0.1:42000/
↓
private admin portal
Private hostnames must be protected by Cloudflare Access or equivalent identity-aware controls.
For admin services, the required current pattern is:
jh-admin.darkhorsekarma.net
↓
Cloudflare Access
↓
Cloudflare Tunnel
↓
127.0.0.1:42000
↓
admin gateway
The admin hostname must not expose internal tools without authentication.
The current public site preview tunnel route is also protected by Cloudflare Access because it is a local development copy, not the production public website. The customer-facing production public website is separate from the tunnel-mapped local preview.
The current production public website remains:
https://justheadlines.pages.dev/
The current local public site preview tunnel route is:
https://jh-site.darkhorsekarma.net/
The two URLs must not be treated as interchangeable. The production public website is the deployed customer-facing site. The tunnel URL is authenticated access to the local development copy served from the server machine.
If separate subdomains are later used for specific internal tools, those subdomains should still follow the same port block logic and must still be protected.
15. Public Versus Private Exposure
The site block is for public customer-facing web work.
The admin block is for private operator, employee, and AI-agent work.
The app block is for the SaaS core application and backend services.
A public hostname should not expose the admin block.
An admin hostname should not expose customer-facing content unless intentionally linked as an external resource.
An app hostname should not expose backend control surfaces without careful authentication and access rules.
The port block standard helps maintain these boundaries, but it does not enforce them by itself.
Access control, routing, repository separation, and deployment configuration enforce them.
16. Current Browser Access Model for Assigned Gateway Ports
The current assigned gateway ports can now be reached in two different ways, depending on where the browser is running and what kind of access is needed.
The server-local access model is:
Browser running on the server machine
↓
http://127.0.0.1:43000/ or http://127.0.0.1:42000/
↓
local service
The remote authenticated browser-access model is:
Browser running on any internet-connected device
↓
Cloudflare Tunnel URL
↓
Cloudflare Access login
↓
Cloudflare Tunnel
↓
cloudflared connector on the server machine
↓
127.0.0.1 assigned local origin port
↓
local service
Use the local address when the task is about confirming whether the server process is running, checking the local service directly, validating a startup command, or troubleshooting whether the origin service itself responds.
Use the Cloudflare Tunnel URL when the task is about viewing the service from a non-server device, sharing authenticated access with an approved person, testing Cloudflare Access, checking the browser experience outside the server machine, or using an AI-agent/browser workflow that cannot browse from the server desktop.
Current use rules:
Use http://127.0.0.1:43000/ on the server machine for direct public site preview checks.
Use https://jh-site.darkhorsekarma.net/ from other devices for authenticated access to the public site preview.
Use http://127.0.0.1:42000/ on the server machine for direct admin portal checks.
Use https://jh-admin.darkhorsekarma.net/ from other devices for authenticated access to the private admin portal.
Cloudflare Tunnel does not make the local service a public unrestricted service. Access is controlled by the Cloudflare Access application and its policies. The local service still listens on 127.0.0.1; the tunnel connector is the component that reaches that local origin on behalf of authenticated browser traffic.
17. Repository Relationship
The current project uses three primary repositories:
site = customer-facing website
admin = private company/admin portal
news = current SaaS application repository, planned rename to app
The port blocks align with these repository boundaries:
site → 43000–43999
admin → 42000–42999
news/app → 41000–41999
The repository boundary and port block boundary should reinforce one another.
If a future AI agent is working in the admin repository and needs a local development server, it should use the admin block unless a task explicitly says otherwise.
If Codex is working in the site repository and needs to preview public customer-facing content, it should use the site block.
If a backend service in the news/app repository needs a local status endpoint, API, or service preview, it should use the app block.
18. AI-Agent and Automation Use
This standard is designed to be readable by AI agents and automation tools.
Future AI agents should use this document to answer questions such as:
- Which port block should I use for a new admin dashboard?
- Which port block should I use for a public site preview?
- Which port block should I use for a backend app status service?
- Should this be a new port or a new path under an existing server?
- Should this be temporary or permanent?
- Should this be documented in the port registry?
The standard answer should be:
- Use the correct project block.
- Use the main gateway port if serving the main portal or primary preview.
- Use a subservice port only if a separate local server process is required.
- Do not assign a permanent port without documenting it.
- Use the experiments block if the service is temporary or exploratory.
- Promote the service into the correct permanent block if it becomes durable.
19. When to Assign a New Port
A new port should be assigned when a separate local process needs to listen for HTTP or another network protocol.
Examples of when a new port may be appropriate:
- a separate React development server
- a dashboard app that runs independently
- a local API service
- a websocket service
- a local reverse proxy
- a webhook receiver
- an AI-agent control surface
- a worker status server
- a database viewer
- a service that cannot be served as static files under the existing gateway
A new port should not be assigned merely because there is a new page, route, folder, document category, report type, or dashboard link.
If a page can be served by the existing gateway as a normal path, it should usually be a path, not a new port.
20. Port Assignment Decision Tree
Use this decision process before assigning a port.
Step 1: Is this a separate running local server process?
If no, do not assign a new port. Use an existing site path.
If yes, continue.
Step 2: Which project area owns the service?
- SaaS app/core backend → 41000 block
- Admin/private portal → 42000 block
- Public customer site → 43000 block
- Shared local infrastructure → 44000 block
- Temporary experiment → 45000 block
Step 3: Is this the main gateway or primary preview for that project area?
If yes, use the 4X000 port assigned to that block.
If no, continue.
Step 4: Is this a durable subservice?
If yes, assign the next appropriate open port in the block and document it.
If no, use the experiments block.
Step 5: Does this need Cloudflare Tunnel exposure?
If yes, prefer exposing the main gateway rather than many subservices directly, unless there is a documented reason to expose a separate hostname.
Step 6: Is the service private?
If yes, require Cloudflare Access or equivalent protection before exposing it through a public hostname.
Step 7: Is the service one of the current assigned tunnel-mapped gateways?
If the service is the public site preview on port 43000, the current tunnel hostname is:
https://jh-site.darkhorsekarma.net/
If the service is the private admin portal on port 42000, the current tunnel hostname is:
https://jh-admin.darkhorsekarma.net/
Use these existing tunnel routes before creating any new tunnel hostname for the same service.
21. Port Registry Requirement
Permanent port assignments should be recorded in a port registry.
The registry may live in a Markdown file such as:
admin/documents_source/standards/local-server-port-registry.md
or another approved internal documentation location.
The registry should include:
Port
Block
Repository
Service name
Purpose
Status
Binding address
Cloudflare Tunnel hostname, if any
Cloudflare Access requirement, if any
Owner
Date assigned
Notes
Suggested statuses:
Reserved
Assigned
Temporary
Deprecated
Retired
A port should not be reused casually after retirement if logs, scripts, docs, or tunnel configs may still refer to it.
For the current assigned gateway services, the registry should record these tunnel hostnames:
42000 → https://jh-admin.darkhorsekarma.net/
43000 → https://jh-site.darkhorsekarma.net/
If a service has no tunnel route, the registry should say None or TBD, depending on whether tunnel exposure is intentionally absent or merely undecided.
22. Naming Standards for Services
A port assignment should have a clear service name.
Avoid vague names such as:
test
server
thing
dashboard2
new-app
Prefer names that identify the repo and purpose:
admin-portal-gateway
site-public-preview
app-feed-processor-status
shared-local-proxy
experiment-react-dashboard
Names should be stable enough for documentation, scripts, logs, and future AI-agent instructions.
23. Binding Standard
Unless otherwise documented, local services should bind to:
127.0.0.1
Example:
py -m http.server 43000 --bind 127.0.0.1 --directory public
This binds the server only to the local loopback interface.
Do not bind to all interfaces:
py -m http.server 43000 --bind 0.0.0.0 --directory public
unless there is a documented reason and the exposure has been reviewed.
24. Command Examples
The examples in this section are conceptual and should not be treated as permanent assignments unless recorded in the official port registry.
24.1 Static Site Preview Example
Conceptual example for serving a static public site preview from a project block gateway port:
cd C:\dev\site
py -m http.server 43000 --bind 127.0.0.1 --directory public
Then visit:
http://127.0.0.1:43000/
If the documentation library is under /docs/, it would be reached through the same server:
http://127.0.0.1:43000/docs/
24.2 Admin Portal Preview Example
Conceptual example for serving an admin portal preview:
cd C:\devdmin
py -m http.server 42000 --bind 127.0.0.1 --directory public
Then visit:
http://127.0.0.1:42000/
If the admin document library is under /documents/, it would be reached through the same server:
http://127.0.0.1:42000/documents/
24.3 Separate Development Server Example
Conceptual example only:
If a dashboard is later built as a separate React app and cannot be served directly as static files through the main admin gateway during development, it may need its own local development server inside the admin block.
That does not mean every dashboard needs its own port. It only means a separate port is appropriate when the dashboard is a separate running server process.
25. Avoiding Port Sprawl
The goal is organized scalability, not unnecessary multiplication of ports.
Do not assign a new port for every page.
Do not assign a new port for every document category.
Do not assign a new port for every dashboard if the dashboards are served by the same app.
Do not assign a new port for a feature that can be routed under an existing gateway.
Use new ports only when separate server processes or separate service boundaries require them.
The existence of 999 assignable ports in a block is capacity, not a requirement to use them.
26. Documentation Requirement Before Cloudflare Tunnel Work
Before a local service is mapped through Cloudflare Tunnel, the following should be known and documented:
- Which repository owns the service.
- Which port block applies.
- Which local port is assigned.
- Whether the service is a gateway or subservice.
- Whether the service is public or private.
- Which hostname will route to it.
- Whether Cloudflare Access is required.
- Whether the service binds to
127.0.0.1. - Whether the service exposes sensitive data.
- Whether the service performs actions or only displays information.
For private admin services, Cloudflare Access or equivalent identity protection should be considered required.
For the current tunnel implementation, the required documented values are:
Public site preview
Local origin: http://127.0.0.1:43000/
Tunnel hostname: https://jh-site.darkhorsekarma.net/
Repository: site
Source path: C:\dev\site\public
Access layer: Cloudflare Access
Private admin portal
Local origin: http://127.0.0.1:42000/
Tunnel hostname: https://jh-admin.darkhorsekarma.net/
Repository: admin
Source path: C:\dev\admin
Access layer: Cloudflare Access
When documenting browser access for either of these services, include both the local origin and the tunnel URL if the distinction matters. The local origin explains where the server process is running. The tunnel URL explains how an approved browser user reaches that same local service from outside the server machine.
27. Public Site Standard
The public site should normally use the site block.
Main public site local preview:
43000
The public site can serve its own pages, documentation library, account pages, support pages, and public content through normal URL paths under the same server.
A separate port inside the site block should only be used when a separate local process is needed.
The public site repository should remain customer-facing only. Internal admin content should not be placed in the public site repository.
The current assigned public site local preview is:
http://127.0.0.1:43000/
The current authenticated Cloudflare Tunnel browser URL for that local preview is:
https://jh-site.darkhorsekarma.net/
Use the local address when checking the public site preview directly on the server machine.
Use the tunnel URL when viewing the local public site preview from another device or from an authenticated browser workflow that reaches the service through Cloudflare.
This tunnel route is not the production public website. The production public website remains separate.
28. Admin Portal Standard
The admin portal should normally use the admin block.
Main admin local preview or gateway:
42000
The admin portal should function as a private command center.
It may include:
- Documents
- Reports
- Dashboards
- Tools
- Status
- Logs
- Agents
- Links
These should usually be paths under the main admin gateway unless a section is implemented as a separate local service.
The admin portal must be treated as private. If exposed through Cloudflare Tunnel, it must be protected through Cloudflare Access or equivalent controls.
The current assigned admin portal local preview is:
http://127.0.0.1:42000/
The current authenticated Cloudflare Tunnel browser URL for the admin portal is:
https://jh-admin.darkhorsekarma.net/
Use the local address when checking the admin portal directly on the server machine.
Use the tunnel URL when viewing the admin portal from another device or from an authenticated browser workflow that reaches the service through Cloudflare.
Because this is the private company access portal, Cloudflare Access protection is required for this hostname. The admin tunnel URL should not be converted into a public bypass route.
29. App / SaaS Core Standard
The SaaS app/core backend should normally use the app block.
Main app local gateway or primary service:
41000
This block is for backend services, status endpoints, local APIs, worker control surfaces, and SaaS application interfaces.
The app block should be treated carefully because it may eventually expose operational or customer-related data.
Any app service exposed remotely must be reviewed for access control and data sensitivity.
30. Shared Infrastructure Standard
The shared infrastructure block is for services that are not owned by one repo.
Use this block only when the service is genuinely shared.
Examples include:
- shared reverse proxy
- shared local gateway
- shared MCP server
- shared local auth testing service
- shared webhook receiver
- shared local monitoring service
If a service belongs clearly to site, admin, or app, use that repo’s block instead.
31. Experiments Standard
Temporary experiments should use the experiments block.
The experiments block is intended to prevent temporary work from polluting durable project blocks.
If an experiment becomes permanent, move it into the appropriate durable block and update the port registry.
Do not leave a production-relevant service permanently in the experiments block.
32. Migration and Refactoring Benefits
This standard reduces future migration and refactoring burden.
If ports are randomly assigned, future work requires rediscovery. A developer or AI agent must inspect running processes, scripts, docs, tunnel configs, browser bookmarks, package scripts, and logs to understand what each port means.
With this standard, the port range itself communicates ownership.
If a future migration is needed, the system will already have:
- clear boundaries
- predictable port blocks
- documented ownership
- gateway conventions
- subservice conventions
- public/private separation
- a registry of assignments
This does not eliminate all future refactoring, but it makes any necessary refactor much easier.
33. Common Mistakes to Avoid
Do not treat non-default ports as the main security control.
Do not bind private services to 0.0.0.0 without review.
Do not expose admin services without Cloudflare Access or equivalent protection.
Do not assign a new port for a normal web page.
Do not place internal admin content in the public site repository.
Do not put experimental services permanently into durable blocks without documentation.
Do not reuse retired ports casually.
Do not assume examples in this document are formal assignments.
Do not use common development defaults when the project standard provides a clear block.
Do not assign ports outside the defined blocks unless there is a documented reason.
34. Summary of the Standard
The Just Headlines local server port allocation standard is:
41000–41999 app / SaaS core
42000–42999 admin / private company access portal
43000–43999 site / public customer website
44000–44999 shared local infrastructure
45000–45999 experiments / temporary development
Within each project block:
4X000 main gateway or primary preview
4X001–4X999 assignable related subservices
Use one port when one server can serve everything.
Use additional ports only when additional local server processes are needed.
Bind local services to 127.0.0.1.
Use Cloudflare Tunnel for remote access without inbound router port forwarding.
Use Cloudflare Access or equivalent controls for private/admin services.
Record permanent assignments in a port registry.
Treat examples as conceptual unless explicitly listed as assigned.
Current assigned tunnel-mapped gateway services:
42000 admin/private company access portal http://127.0.0.1:42000/ → https://jh-admin.darkhorsekarma.net/
43000 public customer website preview http://127.0.0.1:43000/ → https://jh-site.darkhorsekarma.net/
For direct server checks, use the 127.0.0.1 address.
For authenticated browser access from other devices, use the Cloudflare Tunnel URL.
The tunnel URL is the external browser route. The local port remains the origin service address.
Appendix A – Quick Reference
41000–41999 app / SaaS core
42000–42999 admin / private company access portal
43000–43999 site / public customer website
44000–44999 shared local infrastructure
45000–45999 experiments / temporary development
4X000 main gateway / primary preview
4X001–4X999 subservices
Bind to: 127.0.0.1
Avoid: 0.0.0.0 unless reviewed
Avoid: 127.0.0.0
Security comes from:
Cloudflare Tunnel
Cloudflare Access
127.0.0.1 binding
no router port forwarding
default-deny private access policies
careful service design
Current assigned tunnel URLs:
43000 → https://jh-site.darkhorsekarma.net/
42000 → https://jh-admin.darkhorsekarma.net/
Current production public website:
https://justheadlines.pages.dev/
Appendix B – Suggested Port Registry Template
# Local Server Port Registry
| Port | Block | Repository | Service Name | Purpose | Status | Bind Address | Tunnel Hostname | Date Assigned | Notes |
|---:|---|---|---|---|---|---|---|---|---|
| 43000 | site | site | site-public-preview | Main public site local preview | Assigned | 127.0.0.1 | TBD | YYYY-MM-DD | Example row only unless formally adopted |
Examples in the template must be replaced with real assignments when the registry is created.
Appendix C – Conceptual PowerShell Pattern
Static preview pattern:
cd C:\dev\<repo>
py -m http.server <assigned-port> --bind 127.0.0.1 --directory public
This pattern is suitable only when the project output is a static public directory.
Dynamic apps, Node servers, React development servers, reverse proxies, dashboards, and agent tools may use different commands, but they should still follow the same port allocation standard.