Skip to content

Commit 7e4386f

Browse files
authored
fix: move installer to npx, add proxy matcher, remove curl endpoint (#337)
1 parent e6d9326 commit 7e4386f

15 files changed

Lines changed: 107 additions & 243 deletions

File tree

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,12 @@
1+
---
2+
"@frontman-ai/nextjs": patch
3+
---
4+
5+
Move installer to npx-only, remove curl|bash endpoint, make --server optional
6+
7+
- Remove API server install endpoint (InstallController + /install routes)
8+
- Make `--server` optional with default `api.frontman.sh`
9+
- Simplify Readline.res: remove /dev/tty hacks, just use process.stdin
10+
- Add `config.matcher` to proxy.ts template and auto-edit LLM rules
11+
- Update marketing site install command from curl to `npx @frontman-ai/nextjs install`
12+
- Update README install instructions

apps/frontman_server/lib/frontman_server_web/controllers/install_controller.ex

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

apps/frontman_server/lib/frontman_server_web/router.ex

Lines changed: 0 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -41,15 +41,6 @@ defmodule FrontmanServerWeb.Router do
4141
get("/ready", HealthController, :ready)
4242
end
4343

44-
# CLI installer routes - no authentication required
45-
# Usage: curl https://frontman.example.com/install | bash
46-
scope "/install", FrontmanServerWeb do
47-
pipe_through(:api)
48-
49-
get("/", InstallController, :index)
50-
get("/nextjs", InstallController, :nextjs)
51-
end
52-
5344
scope "/api", FrontmanServerWeb do
5445
pipe_through([:api_with_session])
5546

apps/marketing/src/components/blocks/install/InstallSteps.astro

Lines changed: 13 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -14,9 +14,9 @@ import astroLogo from '../../../assets/frameworks/astro.svg'
1414
import viteLogo from '../../../assets/frameworks/vite.svg'
1515
1616
const frameworks = [
17-
{ id: 'nextjs', name: 'Next.js', logo: nextjsLogo, installPath: '/install/nextjs', port: '3000' },
18-
{ id: 'astro', name: 'Astro', logo: astroLogo, installPath: '/install/astro', port: '4321' },
19-
{ id: 'vite', name: 'Vite', logo: viteLogo, installPath: '/install/vite', port: '5173' }
17+
{ id: 'nextjs', name: 'Next.js', logo: nextjsLogo, command: 'npx @frontman-ai/nextjs install', port: '3000' },
18+
{ id: 'astro', name: 'Astro', logo: astroLogo, command: 'npx @frontman-ai/astro install', port: '4321' },
19+
{ id: 'vite', name: 'Vite', logo: viteLogo, command: 'npx @frontman-ai/vite install', port: '5173' }
2020
]
2121
---
2222

@@ -39,12 +39,12 @@ const frameworks = [
3939

4040
<div class="framework-tabs">
4141
{frameworks.map((fw, i) => (
42-
<button
43-
class={`framework-tab ${i === 0 ? 'active' : ''}`}
44-
data-framework={fw.id}
45-
data-install-path={fw.installPath}
46-
data-port={fw.port}
47-
>
42+
<button
43+
class={`framework-tab ${i === 0 ? 'active' : ''}`}
44+
data-framework={fw.id}
45+
data-command={fw.command}
46+
data-port={fw.port}
47+
>
4848
<img src={fw.logo.src} alt={fw.name} width="24" height="24" loading="lazy" />
4949
{fw.name}
5050
</button>
@@ -70,7 +70,7 @@ const frameworks = [
7070
</div>
7171
<div class="terminal-body">
7272
<span class="terminal-prompt">$</span>
73-
<code data-install-command>curl https://frontman.sh/install/nextjs | bash</code>
73+
<code data-install-command>npx @frontman-ai/nextjs install</code>
7474
<button class="copy-button" data-copy="install" aria-label="Copy to clipboard">
7575
<svg width="16" height="16" viewBox="0 0 24 24" fill="none" stroke="currentColor" stroke-width="2">
7676
<rect x="9" y="9" width="13" height="13" rx="2" ry="2"></rect>
@@ -343,9 +343,9 @@ const frameworks = [
343343
tabs.forEach((t) => t.classList.remove('active'))
344344
tab.classList.add('active')
345345

346-
const installPath = tab.getAttribute('data-install-path')
347-
if (installCommand && installPath) {
348-
installCommand.textContent = `curl https://frontman.sh${installPath} | bash`
346+
const command = tab.getAttribute('data-command')
347+
if (installCommand && command) {
348+
installCommand.textContent = command
349349
}
350350

351351
const port = tab.getAttribute('data-port')

libs/bindings/src/Readline.res

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,18 @@
11
// Minimal binding for Node.js readline module (CLI prompts)
22

3-
// Raw JS implementation using node:readline/promises.
3+
// Raw JS implementation using node:readline.
44
// Returns null on EOF (Ctrl+D) so callers can distinguish it from empty input (Enter).
55
// IMPORTANT: resolve(answer) must be called BEFORE rl.close() because
66
// rl.close() synchronously emits 'close', which would resolve with null
77
// and silently discard the real answer (a Promise resolves only once).
88
let question: string => promise<Nullable.t<string>> = %raw(`
99
async function(prompt) {
1010
const readline = await import('node:readline');
11+
1112
const rl = readline.createInterface({
1213
input: process.stdin,
1314
output: process.stdout,
15+
terminal: true,
1416
});
1517
return new Promise((resolve) => {
1618
rl.on('close', () => resolve(null));
@@ -22,9 +24,9 @@ let question: string => promise<Nullable.t<string>> = %raw(`
2224
}
2325
`)
2426

25-
// Check if stdin is a TTY (interactive terminal)
27+
// Check if we can prompt interactively.
2628
let isTTY: unit => bool = %raw(`
2729
function() {
28-
return Boolean(process.stdin.isTTY);
30+
return !!process.stdin.isTTY;
2931
}
3032
`)

libs/frontman-nextjs/README.md

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -9,14 +9,10 @@ Next.js integration for Frontman - provides development tools and observability
99
The fastest way to install Frontman is using our CLI installer:
1010

1111
```bash
12-
# Using curl (server host is auto-detected from the URL)
13-
curl https://api.frontman.sh/install/nextjs | bash
12+
npx @frontman-ai/nextjs install
1413

15-
# For local development
16-
curl http://frontman.local:4000/install/nextjs | bash
17-
18-
# Or using npx directly
19-
npx @frontman-ai/nextjs install --server api.frontman.sh
14+
# Or with a custom server host
15+
npx @frontman-ai/nextjs install --server frontman.company.com
2016
```
2117

2218
The installer will:
@@ -31,7 +27,7 @@ The installer will:
3127
npx @frontman-ai/nextjs install [options]
3228

3329
Options:
34-
--server <host> Frontman server host (required)
30+
--server <host> Frontman server host (default: api.frontman.sh)
3531
--prefix <path> Target directory (default: current directory)
3632
--dry-run Preview changes without writing files
3733
--skip-deps Skip dependency installation
@@ -101,6 +97,10 @@ export function proxy(req: NextRequest): NextResponse | Promise<NextResponse> {
10197
}
10298
return NextResponse.next();
10399
}
100+
101+
export const config = {
102+
matcher: ['/frontman', '/frontman/:path*'],
103+
};
104104
```
105105

106106
### OpenTelemetry Setup (Recommended)
@@ -176,6 +176,11 @@ export function proxy(req: NextRequest): NextResponse | Promise<NextResponse> {
176176
// ... your existing proxy logic below
177177
return NextResponse.next();
178178
}
179+
180+
export const config = {
181+
// Add Frontman matcher alongside your existing matchers
182+
matcher: ['/frontman', '/frontman/:path*', '/your-other-routes/:path*'],
183+
};
179184
```
180185

181186
### Existing instrumentation.ts

libs/frontman-nextjs/package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "@frontman-ai/nextjs",
3-
"version": "0.2.1",
3+
"version": "0.2.4",
44
"description": "Next.js integration for Frontman - AI-powered development tools and observability",
55
"type": "module",
66
"main": "./dist/index.js",

0 commit comments

Comments
 (0)