Skip to content

Commit 7c44e6e

Browse files
authored
feat(cli)!: default dev/start port to 8080 instead of 3000 (#97)
* feat(cli)!: default dev/start port to 8080 instead of 3000 Change the fallback port in `webjs dev` / `webjs start` from 3000 to 8080 (process.env.PORT still wins, so deploys that inject PORT are unaffected). 3000 is heavily contested locally (Next.js, CRA, Express, Flask all default there); 8080 collides less for the scaffolded-app experience. Also updates the OAuth redirect's no-request fallback origin in auth.js from localhost:3000 to localhost:8080 so dev OAuth URLs match the new default. Scaffolded apps pick this up for free: their package.json scripts stay `webjs dev` / `webjs start` (no --port), so they inherit the new default with zero template changes and full cross-platform behavior. BREAKING: existing apps that relied on the implicit 3000 default will now serve on 8080 locally after upgrading @webjsdev/cli. Set PORT=3000 or pass --port 3000 to keep the old port. * docs: update default-port references from 3000 to 8080 Sweep docs, scaffold templates, and package READMEs to reflect the new 8080 default (getting-started, configuration, deployment, websockets, backend-only, server-actions pages; scaffold .env.example + CONVENTIONS; scaffold success message; cli/create-webjs/server READMEs; agent-docs; root README quickstart). Word-boundary match preserves the 30000ms interval example in the controllers page. The blog's own .env.example port is left to the dev-ports change. * fix(server): default startServer port to 8080, matching the CLI startServer's own `opts.port ?? 3000` fallback was missed when the CLI default moved to 8080. The CLI always passes an explicit port, so this only affected programmatic startServer callers and embedders, but it left an inconsistent 3000 default. Align it with the new 8080 default.
1 parent 18f83b5 commit 7c44e6e

18 files changed

Lines changed: 45 additions & 45 deletions

File tree

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ TypeScript with zero build step, real SSR with Declarative Shadow DOM.
5252
# Get started in one command (no global install required)
5353
npm create webjs@latest my-app # full-stack (pages + API + components + Prisma/SQLite)
5454
cd my-app && npm run dev
55-
# → http://localhost:3000
55+
# → http://localhost:8080
5656

5757
# Backend-only API
5858
npm create webjs@latest my-api -- --template api

agent-docs/built-ins.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -106,7 +106,7 @@ JWT sessions by default (stateless, scales horizontally). OAuth providers handle
106106
| `AUTH_GITHUB_ID` / `AUTH_GITHUB_SECRET` | GitHub OAuth (optional) |
107107
| `SESSION_SECRET` | Cookie session signing |
108108
| `REDIS_URL` | When set, sessions + rate limit + cache use Redis |
109-
| `PORT` | Server port (default 3000) |
109+
| `PORT` | Server port (default 8080) |
110110

111111
## Scaling to multiple instances
112112

docs/app/docs/backend-only/page.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ const events = await richFetch('/api/events');
203203
// events[0].createdAt is a real Date object
204204
205205
// External client (curl, Postman) gets plain JSON automatically
206-
// curl http://localhost:3000/api/events</pre>
206+
// curl http://localhost:8080/api/events</pre>
207207
<p>The <code>json()</code> helper reads the <code>Accept</code> header. If the client sent <code>Accept: application/vnd.webjs+json</code> (as <code>richFetch</code> does), the response is encoded with the webjs serializer. Otherwise, plain <code>application/json</code>. The <code>Vary: Accept</code> header is set automatically.</p>
208208
<p>For reading request bodies with the same content negotiation, use <code>readBody(req)</code> from <code>@webjsdev/server</code>.</p>
209209
@@ -250,7 +250,7 @@ fastify.all('*', async (request, reply) =&gt; {
250250
reply.send(body);
251251
});
252252
253-
fastify.listen({ port: 3000 });</pre>
253+
fastify.listen({ port: 8080 });</pre>
254254
255255
<h2>Comparison with Express/Fastify</h2>
256256
<p>Here is what webjs gives you compared to a traditional Node.js API framework:</p>
@@ -329,9 +329,9 @@ export async function POST(req: Request) {
329329
330330
<h3>Run it</h3>
331331
<pre>webjs dev
332-
# API is live at http://localhost:3000
333-
# curl http://localhost:3000/api/posts
334-
# curl http://localhost:3000/__webjs/health</pre>
332+
# API is live at http://localhost:8080
333+
# curl http://localhost:8080/api/posts
334+
# curl http://localhost:8080/__webjs/health</pre>
335335
<p>No pages, no layouts, no components, no SSR. Just a fast, typed API server with file-based routing.</p>
336336
`;
337337
}

docs/app/docs/configuration/page.ts

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -9,19 +9,19 @@ export default function Configuration() {
99
1010
<h2>CLI Options</h2>
1111
<h3>webjs dev</h3>
12-
<pre>webjs dev [--port 3000]</pre>
12+
<pre>webjs dev [--port 8080]</pre>
1313
<ul>
14-
<li><code>--port</code>: dev server port (default: <code>3000</code>, or <code>PORT</code> env var)</li>
14+
<li><code>--port</code>: dev server port (default: <code>8080</code>, or <code>PORT</code> env var)</li>
1515
<li>File watching via chokidar (automatic)</li>
1616
<li>Live reload via SSE (<code>/__webjs/events</code>)</li>
1717
<li>TypeScript files transformed on the fly</li>
1818
<li>No cache-busting needed, since module loads are busted per request</li>
1919
</ul>
2020
2121
<h3>webjs start</h3>
22-
<pre>webjs start [--port 3000]</pre>
22+
<pre>webjs start [--port 8080]</pre>
2323
<ul>
24-
<li><code>--port</code>: production server port (also honors the <code>PORT</code> env var, default 3000)</li>
24+
<li><code>--port</code>: production server port (also honors the <code>PORT</code> env var, default 8080)</li>
2525
<li>Speaks plain HTTP/1.1. TLS termination + HTTP/2 to the browser is the proxy's job (PaaS edges or nginx/Caddy/Traefik)</li>
2626
<li>gzip/brotli compression enabled by default</li>
2727
<li>Static file ETag + Cache-Control headers</li>
@@ -104,7 +104,7 @@ class Checkout extends WebComponent {
104104
// Option 1: Full server
105105
await startServer({
106106
appDir: process.cwd(),
107-
port: 3000,
107+
port: 8080,
108108
dev: false,
109109
compress: true,
110110
http2: false,

docs/app/docs/deployment/page.ts

Lines changed: 15 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,10 @@ export default function Deployment() {
1010
<h2>Dev vs Prod</h2>
1111
<p>webjs has two modes, controlled by the npm script (which wraps the underlying <code>webjs dev</code> / <code>webjs start</code> CLI):</p>
1212
<pre># Development: live reload, no compression, no caching, verbose errors
13-
npm run dev -- --port 3000
13+
npm run dev -- --port 8080
1414
1515
# Production: compression, ETags, cache headers, graceful shutdown
16-
npm run start -- --port 3000</pre>
16+
npm run start -- --port 8080</pre>
1717
<p>Key differences:</p>
1818
<ul>
1919
<li><strong>Dev:</strong> chokidar watches your source tree and triggers live reload via SSE. TypeScript files are served with <code>Cache-Control: no-cache</code>. Errors include full stack traces. No compression.</li>
@@ -55,13 +55,13 @@ GET /__webjs/ready # { "status": "ok" }</pre>
5555
livenessProbe:
5656
httpGet:
5757
path: /__webjs/health
58-
port: 3000
58+
port: 8080
5959
initialDelaySeconds: 5
6060
periodSeconds: 10
6161
readinessProbe:
6262
httpGet:
6363
path: /__webjs/ready
64-
port: 3000
64+
port: 8080
6565
initialDelaySeconds: 3
6666
periodSeconds: 5</pre>
6767
@@ -77,10 +77,10 @@ readinessProbe:
7777
<h2>Pluggable Logger</h2>
7878
<p>webjs includes a minimal logger that writes structured JSON in production and human-readable lines in development:</p>
7979
<pre># Dev output:
80-
[webjs] webjs dev server ready on http://localhost:3000
80+
[webjs] webjs dev server ready on http://localhost:8080
8181
8282
# Prod output (one JSON line per event):
83-
{"level":"info","msg":"webjs prod server ready on http://localhost:3000","time":"2026-01-15T10:30:00.000Z"}</pre>
83+
{"level":"info","msg":"webjs prod server ready on http://localhost:8080","time":"2026-01-15T10:30:00.000Z"}</pre>
8484
<p>Replace it with your own logger by passing any object with <code>info</code>, <code>warn</code>, and <code>error</code> methods to <code>createRequestHandler</code>:</p>
8585
<pre>import { createRequestHandler } from '@webjsdev/server';
8686
import pino from 'pino';
@@ -139,15 +139,15 @@ server.all('*', async (req, res) =&gt; {
139139
res.end();
140140
});
141141
142-
server.listen(3000);</pre>
142+
server.listen(8080);</pre>
143143
144144
<h3>Bun</h3>
145145
<pre>import { createRequestHandler } from '@webjsdev/server';
146146
147147
const app = await createRequestHandler({ appDir: process.cwd(), dev: false });
148148
149149
Bun.serve({
150-
port: 3000,
150+
port: 8080,
151151
fetch: (req) =&gt; app.handle(req),
152152
});</pre>
153153
@@ -156,12 +156,12 @@ Bun.serve({
156156
157157
const app = await createRequestHandler({ appDir: Deno.cwd(), dev: false });
158158
159-
Deno.serve({ port: 3000 }, (req) =&gt; app.handle(req));</pre>
159+
Deno.serve({ port: 8080 }, (req) =&gt; app.handle(req));</pre>
160160
161161
<h2>Environment Variables</h2>
162162
<p>webjs reads the following environment variables:</p>
163163
<ul>
164-
<li><strong>PORT</strong>: server port (default: 3000). Overridden by <code>--port</code> CLI flag.</li>
164+
<li><strong>PORT</strong>: server port (default: 8080). Overridden by <code>--port</code> CLI flag.</li>
165165
<li><strong>NODE_ENV</strong>: not directly used by webjs (it uses the <code>dev</code> flag from the CLI command), but your app code and dependencies may read it.</li>
166166
</ul>
167167
<p>For app-specific environment variables, use <code>process.env</code> in server-side code (pages, server actions, middleware, API routes). These are never exposed to the client.</p>
@@ -184,8 +184,8 @@ RUN npm ci --omit=dev
184184
# Copy app source as-is; the server serves it directly
185185
COPY . .
186186
187-
EXPOSE 3000
188-
HEALTHCHECK CMD curl -f http://localhost:3000/__webjs/health || exit 1
187+
EXPOSE 8080
188+
HEALTHCHECK CMD curl -f http://localhost:8080/__webjs/health || exit 1
189189
190190
CMD ["npx", "webjs", "start"]</pre>
191191
<p>Tips:</p>
@@ -202,7 +202,7 @@ CMD ["npx", "webjs", "start"]</pre>
202202
203203
<h3>nginx</h3>
204204
<pre>upstream webjs {
205-
server 127.0.0.1:3000;
205+
server 127.0.0.1:8080;
206206
}
207207
208208
server {
@@ -227,7 +227,7 @@ server {
227227
228228
<h3>Caddy</h3>
229229
<pre>example.com {
230-
reverse_proxy localhost:3000
230+
reverse_proxy localhost:8080
231231
}</pre>
232232
<p>Caddy automatically provisions TLS certificates via Let's Encrypt and enables HTTP/2. It also handles WebSocket upgrades transparently.</p>
233233
@@ -243,7 +243,7 @@ After=network.target
243243
Type=simple
244244
User=www
245245
WorkingDirectory=/srv/my-app
246-
ExecStart=/usr/bin/webjs start --port 3000
246+
ExecStart=/usr/bin/webjs start --port 8080
247247
Restart=on-failure
248248
RestartSec=5
249249
Environment=NODE_ENV=production

docs/app/docs/getting-started/page.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ npm i -g @webjsdev/cli
2020
# scaffold a new app
2121
webjs create my-app
2222
cd my-app && npm run dev
23-
# → http://localhost:3000</pre>
23+
# → http://localhost:8080</pre>
2424
2525
<p>Every scaffold ships with Prisma + SQLite wired up (<code>prisma/schema.prisma</code> with an example <code>User</code> model and <code>lib/prisma.server.ts</code> singleton). Run <code>npm run db:migrate</code> the first time to create <code>prisma/dev.db</code>.</p>
2626
@@ -116,7 +116,7 @@ Counter.register('my-counter');</pre>
116116
117117
<h3>Run it</h3>
118118
<pre>npm run dev
119-
# → http://localhost:3000</pre>
119+
# → http://localhost:8080</pre>
120120
121121
<p>That's it. No build step, no bundler config, no compilation. Edit any <code>.ts</code> file, refresh, and see it.</p>
122122

docs/app/docs/server-actions/page.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -337,7 +337,7 @@ export class TodoApp extends WebComponent {
337337
TodoApp.register('todo-app');
338338
339339
// 3. Call the REST endpoint from curl
340-
// curl -X POST http://localhost:3000/api/todos \\
340+
// curl -X POST http://localhost:8080/api/todos \\
341341
// -H 'Content-Type: application/json' \\
342342
// -d '{"text":"Buy milk"}'
343343
// => {"id":1,"text":"Buy milk","done":false,"createdAt":"2026-04-15T..."}</pre>

docs/app/docs/websockets/page.ts

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -128,7 +128,7 @@ conn.close();</pre>
128128
<h3>URL Resolution</h3>
129129
<p>Relative paths like <code>'/api/chat'</code> are automatically promoted to the correct WebSocket URL based on the current page's protocol:</p>
130130
<ul>
131-
<li><code>http://</code> page: <code>ws://localhost:3000/api/chat</code></li>
131+
<li><code>http://</code> page: <code>ws://localhost:8080/api/chat</code></li>
132132
<li><code>https://</code> page: <code>wss://example.com/api/chat</code></li>
133133
</ul>
134134
<p>Absolute <code>ws://</code> or <code>wss://</code> URLs pass through unchanged.</p>
@@ -498,7 +498,7 @@ export function WS(ws: WebSocket) {
498498
import type { WebSocket } from 'ws';
499499
500500
export function WS(ws: WebSocket, req: Request, { params }: { params: { roomId: string } }) {
501-
const room = params.roomId; // e.g. "general" for ws://localhost:3000/api/rooms/general
501+
const room = params.roomId; // e.g. "general" for ws://localhost:8080/api/rooms/general
502502
joinRoom(room, ws);
503503
ws.on('message', (data) =&gt; broadcastToRoom(room, data.toString(), ws));
504504
ws.on('close', () =&gt; leaveRoom(room, ws));

examples/blog/CONVENTIONS.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -209,7 +209,7 @@ variables control infrastructure (no config files needed):
209209
| `AUTH_SECRET` | Required for auth JWT signing (32+ random chars) |
210210
| `AUTH_GOOGLE_ID` | Google OAuth client ID (optional) |
211211
| `AUTH_GITHUB_ID` | GitHub OAuth client ID (optional) |
212-
| `PORT` | Server port (default: 3000) |
212+
| `PORT` | Server port (default: 8080) |
213213
| `WEBJS_PUBLIC_*` | Any env var starting with this prefix is exposed to the browser as `process.env.WEBJS_PUBLIC_X`. Components can read it directly. No build step, no transform. Use for API base URLs, Stripe publishable keys, analytics IDs, anything that is intended to be visible client-side. |
214214

215215
**Server-only by default.** Any env var without the `WEBJS_PUBLIC_` prefix never reaches the browser. Reading `process.env.DATABASE_URL` from a component returns `undefined`, the same as a typo. The prefix is fail-closed: secrets cannot accidentally leak.

packages/cli/README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ Then scaffold a new app anywhere:
1818
```sh
1919
webjs create my-app
2020
cd my-app && npm run dev
21-
# → http://localhost:3000
21+
# → http://localhost:8080
2222
```
2323

2424
One-shot without a global install, two ways:

0 commit comments

Comments
 (0)