next-image-transformer 0.2.4 → 0.2.10

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (2) hide show
  1. package/README.md +155 -0
  2. package/package.json +5 -5
package/README.md CHANGED
@@ -1 +1,156 @@
1
1
  # next-image-transformer
2
+
3
+ Self-hosted, Sharp-powered runtime image transforms for Next.js.
4
+
5
+ Next.js’s built-in image optimization (`next/image` + the `/_next/image` optimizer) is intentionally **constrained and opinionated**. If you want something closer to “Imgix/Cloudinary, but inside your Next.js app,” this package gives you:
6
+
7
+ - A **route handler** that fetches an upstream image, runs a small set of transforms via **Sharp**, and caches results on disk.
8
+ - A **URL builder** that creates transform URLs you can use from your app.
9
+
10
+ This tends to work best on managed app hosting where you run a Node runtime and can put a CDN in front:
11
+
12
+ - DigitalOcean App Platform (CDN-enabled)
13
+ - Render, Fly.io, Railway, Heroku
14
+ - AWS App Runner / ECS / EC2 (often fronted by CloudFront)
15
+ - Google Cloud Run (often fronted by Cloud CDN)
16
+ - Any setup fronted by Cloudflare / Fastly / etc.
17
+
18
+ ### Installation (Next.js App Router)
19
+
20
+ #### 1) Install:
21
+
22
+ ```bash
23
+ yarn add next-image-transformer sharp
24
+ ```
25
+
26
+ #### 2) Add a route handler
27
+
28
+ Create a [route handler](https://nextjs.org/docs/app/getting-started/route-handlers) at some path, for example: `src/app/image/route.ts`
29
+
30
+ ```ts
31
+ // src/app/api/image/route.ts
32
+
33
+ import { createImageTransformRouteHandler } from "next-image-transformer/server";
34
+
35
+ export const runtime = "nodejs";
36
+
37
+ const handler = createImageTransformRouteHandler({
38
+ // Must be an absolute URL. This is used to build a canonical URL for caching.
39
+ apiRouteUrl:
40
+ process.env.IMAGE_TRANSFORM_API_URL ?? "http://localhost:3000/api/image",
41
+ });
42
+
43
+ export const GET = handler;
44
+ ```
45
+
46
+ #### 3) Create a URL builder module
47
+
48
+ Create a helper for example: `src/lib/imageUrlBuilder.ts`
49
+
50
+ ```ts
51
+ import { createImageUrlBuilder } from "next-image-transformer";
52
+
53
+ export const imageUrlBuilder = createImageUrlBuilder({
54
+ // Same absolute URL as the route above, but safe to expose publicly
55
+ // if you want to build URLs client-side.
56
+ apiRouteUrl:
57
+ process.env.NEXT_PUBLIC_IMAGE_TRANSFORM_API_URL ??
58
+ "http://localhost:3000/api/image",
59
+ });
60
+ ```
61
+
62
+ #### 4) Start writing URLs:
63
+
64
+ Then build URLs like:
65
+
66
+ ```tsx
67
+ // src/components/MyImage.tsx
68
+
69
+ import { imageUrlBuilder } from "../lib/imageUrlBuilder";
70
+
71
+ export function MyImage() {
72
+ return (
73
+ <img
74
+ src={imageUrlBuilder.encode({
75
+ source: "https://images.example.com/cat.jpg",
76
+ fmt: "webp",
77
+ w: 800,
78
+ q: 80,
79
+ })}
80
+ />
81
+ );
82
+ }
83
+ ```
84
+
85
+ ### API reference
86
+
87
+ #### `createImageTransformRouteHandler(options)`
88
+
89
+ Import from: `next-image-transformer/server`
90
+
91
+ Returns: `(req: Request) => Promise<Response>` (compatible with Next.js Route Handlers)
92
+
93
+ **Options**
94
+
95
+ - **`apiRouteUrl`**: `string` (required)
96
+ - **Description**: Absolute URL for the transform route (used to generate a canonical URL for caching).
97
+ - **Default**: none
98
+ - **`cacheDir`**: `string` (optional)
99
+ - **Description**: Directory on disk where transformed images are cached.
100
+ - **Default**: `path.join(process.cwd(), ".transform-cache")`
101
+ - **`cacheControl`**: `string` (optional)
102
+ - **Description**: Value for the response `Cache-Control` header.
103
+ - **Default**: `"public, max-age=31536000, immutable"`
104
+ - **`allowedHosts`**: `Array<string | RegExp>` (optional)
105
+ - **Description**: Allowlist for the upstream `source` URL host. If omitted, **all hosts are allowed**.
106
+ - Exact host: `"images.example.com"`
107
+ - Host + port: `"localhost:3000"`
108
+ - RegExp: `/^(?:.+\.)?example\.com$/` (tested against both `hostname` and `host`)
109
+ - **Default**: `undefined` (allow all)
110
+
111
+ **Behavior notes**
112
+
113
+ - **Format defaulting**: if `fmt` is omitted in the URL, it defaults to `"preserve"`.
114
+ - **Quality defaulting**: if `q` is omitted, the handler uses `100`.
115
+ - **Resize semantics**: if `w` and/or `h` is provided, the image is resized with:
116
+ - `fit: "inside"`
117
+ - `withoutEnlargement: true`
118
+ - **Auto-orient**: Sharp `rotate()` is applied to respect EXIF orientation.
119
+ - **Caching**: responses are cached on disk; your runtime must have a writable filesystem.
120
+
121
+ #### `createImageUrlBuilder(options)`
122
+
123
+ Import from: `next-image-transformer`
124
+
125
+ Returns: a Zod codec that can:
126
+
127
+ - `encode(config: TransformConfig): string` (builds a URL)
128
+ - `safeDecode(url: string): { data?: TransformConfig; error?: ... }` (parses a URL)
129
+
130
+ **Options**
131
+
132
+ - **`apiRouteUrl`**: `string` (required)
133
+ - **Description**: Absolute URL for your transform route.
134
+ - **Default**: none
135
+
136
+ ### Transform config + query parameters
137
+
138
+ The transform URL uses these query params:
139
+
140
+ - **`source`**: `string` (required)
141
+ - Absolute `http(s)` URL to the upstream image.
142
+ - **`fmt`**: `"preserve" | "webp" | "avif"` (optional in the URL)
143
+ - **Default (when decoding)**: `"preserve"`
144
+ - **`w`**: `number` (optional)
145
+ - 32-bit integer
146
+ - **`h`**: `number` (optional)
147
+ - 32-bit integer
148
+ - **`q`**: `number` (optional)
149
+ - Integer in `[0..100]`
150
+ - **Default (when transforming)**: `100`
151
+
152
+ When building URLs, `fmt=preserve` is omitted from the query string (it’s treated as the “default”).
153
+
154
+ ### License
155
+
156
+ See `LICENSE.md`.
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "next-image-transformer",
3
- "version": "0.2.4",
3
+ "version": "0.2.10",
4
4
  "main": "dist/index.js",
5
5
  "types": "dist/index.d.ts",
6
6
  "exports": {
@@ -24,11 +24,11 @@
24
24
  "README.md",
25
25
  "LICENSE*"
26
26
  ],
27
- "packageManager": "yarn@4.9.2",
27
+ "packageManager": "yarn@4.12.0",
28
28
  "devDependencies": {
29
29
  "@types/node": "24",
30
- "np": "^10.2.0",
31
30
  "prettier": "^3.7.4",
31
+ "release-it": "^19.2.3",
32
32
  "sharp": "^0.34.5",
33
33
  "typescript": "^5.9.3",
34
34
  "vite": "^7.3.0"
@@ -43,6 +43,6 @@
43
43
  },
44
44
  "scripts": {
45
45
  "build": "vite build && tsc",
46
- "release": "yarn build && np --no-tests --no-publish && yarn npm publish"
46
+ "release": "release-it"
47
47
  }
48
- }
48
+ }