Skip to content

Commit f858ef1

Browse files
ralyodioclaude
andauthored
Run on Bun: bun install, bun --bun next, standalone server under Bun (#70)
Moves c0upons.com off Node + pnpm (nixpacks) onto Bun, following the fleet recipe from the phonenumbers.bot pilot. - Package manager: bun.lock migrated from pnpm-lock.yaml (every version kept exact), workspaces moved into package.json, packageManager bun@1.4.0. pnpm-workspace.yaml, pnpm-lock.yaml and the Railway railpack.json are gone. - Runtime: apps/web scripts use `bun --bun next`; next.config adds standalone output traced from the workspace root. - Image: .nixpacks/Dockerfile (the path dev2's compose builds) is a hand-written oven/bun:1.4.0-slim build that runs `bun apps/web/server.js` as the bun user and declares the NEXT_PUBLIC_BASE_URL build arg compose passes. Port 3000, env and the / health path are unchanged. - CI: one Bun workflow (frozen install, typecheck, tests, build, boot the server); the root node:test suite runs under `bun test` unchanged (59 pass). Co-authored-by: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
1 parent 45018be commit f858ef1

14 files changed

Lines changed: 1370 additions & 5670 deletions

‎.dockerignore‎

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
.git
2+
.github
3+
**/node_modules
4+
**/.next
5+
**/.turbo
6+
**/dist
7+
.env*

‎.github/workflows/ci.yml‎

Lines changed: 28 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,5 @@
1-
# Managed by sh1pt Actions Fleet
2-
# pack: node-pnpm-ci@1.0.0
3-
# install: sh1pt-actions-store
4-
# hash: sha256:aa7aeaf3bddaf7bf324ceb02f46ab421bb229d5f5917fdb6f7a1a948a4a9fcce
1+
# Bun CI (was the sh1pt-managed node-pnpm-ci pack; the app moved to Bun, so this
2+
# file is no longer managed by that pack).
53
name: CI
64

75
on:
@@ -18,20 +16,34 @@ concurrency:
1816

1917
jobs:
2018
build:
19+
name: install, typecheck, test, build (Bun)
2120
runs-on: ubuntu-latest
2221
timeout-minutes: 15
2322
steps:
2423
- uses: actions/checkout@v4
25-
26-
- uses: pnpm/action-setup@v4
27-
28-
- uses: actions/setup-node@v4
24+
# The version comes from packageManager in package.json, the same Bun the
25+
# image (.nixpacks/Dockerfile) pins.
26+
- uses: oven-sh/setup-bun@v2
2927
with:
30-
node-version: '22'
31-
cache: pnpm
32-
33-
- run: pnpm install --frozen-lockfile
34-
35-
- run: pnpm typecheck
36-
37-
- run: pnpm test
28+
bun-version-file: package.json
29+
- run: bun install --frozen-lockfile
30+
- run: bun run typecheck
31+
- run: bun run test
32+
env:
33+
CI: true
34+
- run: bun run build:web
35+
env:
36+
NEXT_PUBLIC_BASE_URL: https://c0upons.com
37+
# The production server must boot under Bun and answer.
38+
- name: Standalone server answers under Bun
39+
run: |
40+
cd apps/web
41+
cp -r public .next/standalone/apps/web/
42+
cp -r .next/static .next/standalone/apps/web/.next/
43+
(cd .next/standalone && PORT=3000 HOSTNAME=127.0.0.1 REDDIT_SYNC_INTERVAL_MINUTES=0 GROCERY_SYNC_INTERVAL_MINUTES=0 bun apps/web/server.js > "$RUNNER_TEMP/server.log" 2>&1 &)
44+
for i in $(seq 1 30); do
45+
code=$(curl -s -o /dev/null -w '%{http_code}' -H 'x-forwarded-proto: https' http://127.0.0.1:3000/robots.txt || true)
46+
[ "$code" = 200 ] && { echo "/robots.txt -> $code"; exit 0; }
47+
sleep 1
48+
done
49+
cat "$RUNNER_TEMP/server.log"; exit 1

‎.github/workflows/test.yml‎

Lines changed: 0 additions & 33 deletions
This file was deleted.

‎.nixpacks/Dockerfile‎

Lines changed: 47 additions & 35 deletions
Original file line numberDiff line numberDiff line change
@@ -1,35 +1,47 @@
1-
FROM ghcr.io/railwayapp/nixpacks:ubuntu-1745885067
2-
3-
ENTRYPOINT ["/bin/bash", "-l", "-c"]
4-
WORKDIR /app/
5-
6-
7-
COPY .nixpacks/nixpkgs-23f9169c4ccce521379e602cc82ed873a1f1b52b.nix .nixpacks/nixpkgs-23f9169c4ccce521379e602cc82ed873a1f1b52b.nix
8-
RUN nix-env -if .nixpacks/nixpkgs-23f9169c4ccce521379e602cc82ed873a1f1b52b.nix && nix-collect-garbage -d
9-
10-
11-
ARG CI NIXPACKS_METADATA NODE_ENV NPM_CONFIG_PRODUCTION
12-
ENV CI=$CI NIXPACKS_METADATA=$NIXPACKS_METADATA NODE_ENV=$NODE_ENV NPM_CONFIG_PRODUCTION=$NPM_CONFIG_PRODUCTION
13-
14-
# setup phase
15-
# noop
16-
17-
# install phase
18-
ENV NIXPACKS_PATH=/app/node_modules/.bin:$NIXPACKS_PATH
19-
COPY . /app/.
20-
RUN --mount=type=cache,id=rXquQypSM-/root/local/share/pnpm/store/v3,target=/root/.local/share/pnpm/store/v3 npm install -g corepack@0.24.1 && corepack enable
21-
RUN --mount=type=cache,id=rXquQypSM-/root/local/share/pnpm/store/v3,target=/root/.local/share/pnpm/store/v3 pnpm i --frozen-lockfile
22-
23-
# build phase
24-
COPY . /app/.
25-
RUN --mount=type=cache,id=rXquQypSM-apps/web/next/cache,target=/app/apps/web/.next/cache --mount=type=cache,id=rXquQypSM-node_modules/cache,target=/app/node_modules/.cache npx turbo run build
26-
27-
28-
RUN printf '\nPATH=/app/node_modules/.bin:$PATH' >> /root/.profile
29-
30-
31-
# start
32-
COPY . /app
33-
34-
CMD ["pnpm run start"]
35-
1+
# syntax=docker/dockerfile:1
2+
#
3+
# c0upons.com, run on Bun.
4+
#
5+
# This file lives at .nixpacks/Dockerfile because that is the path dev2's compose
6+
# stack builds (cli-tools dev2/dev2-site provision records it per site). It used to
7+
# be nixpacks output (Node + pnpm); it is now a hand-written Bun image, so do not
8+
# regenerate it with nixpacks.
9+
#
10+
# Contract with /home/anthony/www/c0upons.com on dev2, unchanged: listens on 3000
11+
# inside the container, answers / for the deploy health check, reads its secrets
12+
# from app.env at run time. NEXT_PUBLIC_BASE_URL arrives as a compose build arg.
13+
14+
FROM oven/bun:1.4.0-slim AS deps
15+
WORKDIR /app
16+
# The whole workspace manifest set: bun installs per-package trees.
17+
COPY package.json bun.lock ./
18+
COPY apps/web/package.json apps/web/package.json
19+
COPY apps/cli/package.json apps/cli/package.json
20+
RUN bun install --frozen-lockfile
21+
22+
FROM deps AS build
23+
COPY . .
24+
ARG NEXT_PUBLIC_BASE_URL
25+
ENV NEXT_PUBLIC_BASE_URL=$NEXT_PUBLIC_BASE_URL
26+
ENV NEXT_TELEMETRY_DISABLED=1 TURBO_TELEMETRY_DISABLED=1
27+
# turbo -> `bun --bun next build` in apps/web: Next builds on Bun, not Node.
28+
RUN bun run build:web
29+
30+
FROM oven/bun:1.4.0-slim AS runtime
31+
WORKDIR /app
32+
ENV NODE_ENV=production
33+
ENV NEXT_TELEMETRY_DISABLED=1
34+
ENV PORT=3000
35+
# Docker sets HOSTNAME to the container id and Next's standalone server binds to it
36+
# literally; it must listen on every interface for the published port to reach it.
37+
ENV HOSTNAME=0.0.0.0
38+
# Standalone output traced from the workspace root keeps the apps/web/ layout.
39+
COPY --from=build --chown=bun:bun /app/apps/web/.next/standalone ./
40+
COPY --from=build --chown=bun:bun /app/apps/web/.next/static ./apps/web/.next/static
41+
COPY --from=build --chown=bun:bun /app/apps/web/public ./apps/web/public
42+
USER bun
43+
EXPOSE 3000
44+
# 127.0.0.1, not localhost: localhost resolves ::1 first and Next binds IPv4 only.
45+
HEALTHCHECK --interval=30s --timeout=5s --start-period=20s --retries=3 \
46+
CMD bun -e "fetch('http://127.0.0.1:'+(process.env.PORT||3000)+'/').then(r=>process.exit(r.status<500?0:1)).catch(()=>process.exit(1))"
47+
CMD ["bun", "apps/web/server.js"]

‎.nixpacks/build.sh‎

Lines changed: 0 additions & 1 deletion
This file was deleted.

‎.nixpacks/nixpkgs-23f9169c4ccce521379e602cc82ed873a1f1b52b.nix‎

Lines changed: 0 additions & 21 deletions
This file was deleted.

‎README.md‎

Lines changed: 6 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -5,15 +5,14 @@ This is a [Next.js](https://nextjs.org) project bootstrapped with [`create-next-
55
First, run the development server:
66

77
```bash
8-
npm run dev
9-
# or
10-
yarn dev
11-
# or
12-
pnpm dev
13-
# or
14-
bun dev
8+
bun install
9+
bun run dev:web
1510
```
1611

12+
Bun is the package manager and the runtime (`bun --bun next ...`). Production runs
13+
the standalone server under Bun from the image built by `.nixpacks/Dockerfile`
14+
(`bun apps/web/server.js`). Tests: `bun run test`.
15+
1716
Open [http://localhost:3000](http://localhost:3000) with your browser to see the result.
1817

1918
You can start editing the page by modifying `app/page.tsx`. The page auto-updates as you edit the file.

‎apps/web/next.config.ts‎

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,11 @@ loadRootEnv();
1010
const withSerwist = (cfg: NextConfig) => cfg;
1111

1212
const nextConfig: NextConfig = {
13+
// The image runs the standalone server under Bun (`bun apps/web/server.js`).
14+
output: 'standalone',
15+
// Trace from the workspace root (two levels up), never a lockfile further up the
16+
// disk, so the standalone tree keeps the apps/web/ layout.
17+
outputFileTracingRoot: new URL('../../', import.meta.url).pathname,
1318
reactStrictMode: true,
1419
turbopack: {},
1520
// The database drivers stay out of the server bundle: pg (under

‎apps/web/package.json‎

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -4,13 +4,13 @@
44
"private": true,
55
"type": "module",
66
"scripts": {
7-
"dev": "next dev",
8-
"build": "next build",
9-
"start": "next start",
7+
"dev": "bun --bun next dev",
8+
"build": "bun --bun next build",
9+
"start": "bun --bun next start",
1010
"lint": "eslint app/ components/ lib/",
1111
"test": "echo 'No tests configured'",
1212
"typecheck": "tsc --noEmit",
13-
"db:migrate": "node scripts/migrate.mjs",
13+
"db:migrate": "bun scripts/migrate.mjs",
1414
"clean": "rm -rf .next out node_modules"
1515
},
1616
"dependencies": {

0 commit comments

Comments
 (0)