Skip to content

Commit 58e58da

Browse files
pengyingclaude
andcommitted
feat(samples): serve frontend from Kotlin backend via Gradle build
- Add node-gradle plugin to build frontend as part of ./gradlew run - Vite outputs to backend's src/main/resources/static/ - Ktor serves static files at / (after API routes) - Update README with single-command and dev-server run options Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 03e04db commit 58e58da

5 files changed

Lines changed: 48 additions & 2 deletions

File tree

samples/frontend/vite.config.ts

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,10 @@ import tailwindcss from '@tailwindcss/vite'
44

55
export default defineConfig({
66
plugins: [react(), tailwindcss()],
7+
build: {
8+
outDir: '../kotlin/src/main/resources/static',
9+
emptyOutDir: true,
10+
},
711
server: {
812
port: 5173,
913
proxy: {

samples/kotlin/.gitignore

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
# Gradle
2+
.gradle/
3+
build/
4+
5+
# Frontend build output (generated by vite build)
6+
src/main/resources/static/
7+
8+
# Environment
9+
.env

samples/kotlin/README.md

Lines changed: 15 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,20 @@ Webhook events are streamed to the frontend in real time via Server-Sent Events
3838

3939
## Running
4040

41-
Start the backend and frontend in two separate terminals:
41+
### Option 1: Single command (recommended)
42+
43+
The Gradle build automatically installs frontend dependencies, builds the React app, and serves it from the backend:
44+
45+
```bash
46+
cd samples/kotlin
47+
./gradlew run
48+
```
49+
50+
Open [http://localhost:8080](http://localhost:8080) in your browser.
51+
52+
### Option 2: Separate dev servers (for frontend development)
53+
54+
If you're iterating on the frontend, run them separately for hot reload:
4255

4356
**Terminal 1 — Backend (port 8080):**
4457

@@ -55,7 +68,7 @@ npm install
5568
npm run dev
5669
```
5770

58-
Open [http://localhost:5173](http://localhost:5173) in your browser.
71+
Open [http://localhost:5173](http://localhost:5173) in your browser. The Vite dev server proxies `/api` requests to the backend.
5972

6073
## Webhook Setup
6174

samples/kotlin/build.gradle.kts

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,22 @@ plugins {
22
kotlin("jvm") version "2.1.21"
33
kotlin("plugin.serialization") version "2.1.21"
44
id("io.ktor.plugin") version "3.1.3"
5+
id("com.github.node-gradle.node") version "7.1.0"
6+
}
7+
8+
node {
9+
version.set("22.15.0")
10+
download.set(true)
11+
nodeProjectDir.set(file("../frontend"))
12+
}
13+
14+
val npmBuild by tasks.register<com.github.gradle.node.npm.task.NpmTask>("npmBuild") {
15+
dependsOn(tasks.named("npmInstall"))
16+
args.set(listOf("run", "build"))
17+
}
18+
19+
tasks.named("processResources") {
20+
dependsOn("npmBuild")
521
}
622

723
kotlin {

samples/kotlin/src/main/kotlin/com/grid/sample/Application.kt

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import com.grid.sample.routes.*
44
import io.ktor.http.*
55
import io.ktor.server.application.*
66
import io.ktor.server.plugins.cors.routing.*
7+
import io.ktor.server.http.content.*
78
import io.ktor.server.routing.*
89
import io.ktor.server.sse.*
910

@@ -29,5 +30,8 @@ fun Application.module() {
2930
sandboxRoutes()
3031
webhookRoutes()
3132
sseRoutes()
33+
34+
// Serve frontend static files — must come last to avoid catching API routes
35+
staticResources("/", "static")
3236
}
3337
}

0 commit comments

Comments
 (0)