diff options
| -rw-r--r-- | .env.example | 1 | ||||
| -rw-r--r-- | backend/admin/handler.go | 42 | ||||
| -rw-r--r-- | backend/admin/templates/base.html | 6 | ||||
| -rw-r--r-- | backend/admin/templates/dashboard.html | 10 | ||||
| -rw-r--r-- | backend/admin/templates/game_edit.html | 4 | ||||
| -rw-r--r-- | backend/admin/templates/games.html | 2 | ||||
| -rw-r--r-- | backend/admin/templates/online_qualifying_ranking.html | 2 | ||||
| -rw-r--r-- | backend/admin/templates/user_edit.html | 2 | ||||
| -rw-r--r-- | backend/admin/templates/users.html | 2 | ||||
| -rw-r--r-- | backend/config/config.go (renamed from backend/config.go) | 32 | ||||
| -rw-r--r-- | backend/main.go | 21 | ||||
| -rw-r--r-- | compose.prod.yaml | 1 | ||||
| -rw-r--r-- | docs/DEV.md | 3 | ||||
| -rw-r--r-- | frontend/Dockerfile | 2 | ||||
| -rw-r--r-- | frontend/app/api/client.ts | 5 | ||||
| -rw-r--r-- | frontend/app/components/UserIcon.tsx | 6 | ||||
| -rw-r--r-- | frontend/app/config.ts | 2 | ||||
| -rw-r--r-- | frontend/app/root.tsx | 3 | ||||
| -rw-r--r-- | frontend/app/routes/_index.tsx | 3 | ||||
| -rw-r--r-- | frontend/app/routes/dashboard.tsx | 5 | ||||
| -rw-r--r-- | frontend/react-router.config.ts | 2 | ||||
| -rw-r--r-- | frontend/vite.config.ts | 2 |
22 files changed, 89 insertions, 69 deletions
diff --git a/.env.example b/.env.example index f8186e1..c249872 100644 --- a/.env.example +++ b/.env.example @@ -1,2 +1,3 @@ +ALBATROSS_BASE_PATH=/phperkaigi/2025/code-battle/ ALBATROSS_JWT_SECRET=[your_secret_key] ALBATROSS_COOKIE_SECRET=[your_secret_key] diff --git a/backend/admin/handler.go b/backend/admin/handler.go index 81ea2b7..f7fd63e 100644 --- a/backend/admin/handler.go +++ b/backend/admin/handler.go @@ -14,33 +14,31 @@ import ( "github.com/nsfisis/phperkaigi-2025-albatross/backend/account" "github.com/nsfisis/phperkaigi-2025-albatross/backend/auth" + "github.com/nsfisis/phperkaigi-2025-albatross/backend/config" "github.com/nsfisis/phperkaigi-2025-albatross/backend/db" ) -const ( - basePath = "/phperkaigi/2025/code-battle" -) - var jst = time.FixedZone("Asia/Tokyo", 9*60*60) type Handler struct { - q *db.Queries + q *db.Queries + conf *config.Config } -func NewHandler(q *db.Queries) *Handler { - return &Handler{q: q} +func NewHandler(q *db.Queries, conf *config.Config) *Handler { + return &Handler{q: q, conf: conf} } -func newAdminMiddleware() echo.MiddlewareFunc { +func (h *Handler) newAdminMiddleware() echo.MiddlewareFunc { return func(next echo.HandlerFunc) echo.HandlerFunc { return func(c echo.Context) error { jwt, err := c.Cookie("albatross_token") if err != nil { - return c.Redirect(http.StatusSeeOther, basePath+"/login") + return c.Redirect(http.StatusSeeOther, h.conf.BasePath+"login") } claims, err := auth.ParseJWT(jwt.Value) if err != nil { - return c.Redirect(http.StatusSeeOther, basePath+"/login") + return c.Redirect(http.StatusSeeOther, h.conf.BasePath+"login") } if !claims.IsAdmin { return echo.NewHTTPError(http.StatusForbidden) @@ -52,7 +50,7 @@ func newAdminMiddleware() echo.MiddlewareFunc { func (h *Handler) RegisterHandlers(g *echo.Group) { g.Use(newAssetsMiddleware()) - g.Use(newAdminMiddleware()) + g.Use(h.newAdminMiddleware()) g.GET("/dashboard", h.getDashboard) g.GET("/users", h.getUsers) @@ -69,7 +67,7 @@ func (h *Handler) RegisterHandlers(g *echo.Group) { func (h *Handler) getDashboard(c echo.Context) error { return c.Render(http.StatusOK, "dashboard", echo.Map{ - "BasePath": basePath, + "BasePath": h.conf.BasePath, "Title": "Dashboard", }) } @@ -91,7 +89,7 @@ func (h *Handler) getUsers(c echo.Context) error { } return c.Render(http.StatusOK, "users", echo.Map{ - "BasePath": basePath, + "BasePath": h.conf.BasePath, "Title": "Users", "Users": users, }) @@ -111,7 +109,7 @@ func (h *Handler) getUserEdit(c echo.Context) error { } return c.Render(http.StatusOK, "user_edit", echo.Map{ - "BasePath": basePath, + "BasePath": h.conf.BasePath, "Title": "User Edit", "User": echo.Map{ "UserID": row.UserID, @@ -155,7 +153,7 @@ func (h *Handler) postUserEdit(c echo.Context) error { return echo.NewHTTPError(http.StatusInternalServerError, err.Error()) } - return c.Redirect(http.StatusSeeOther, basePath+"/admin/users") + return c.Redirect(http.StatusSeeOther, h.conf.BasePath+"admin/users") } func (h *Handler) postUserFetchIcon(c echo.Context) error { @@ -177,7 +175,7 @@ func (h *Handler) postUserFetchIcon(c echo.Context) error { // The failure is intentionally ignored. Retry manually if needed. } }() - return c.Redirect(http.StatusSeeOther, basePath+"/admin/users") + return c.Redirect(http.StatusSeeOther, h.conf.BasePath+"admin/users") } func (h *Handler) getGames(c echo.Context) error { @@ -203,7 +201,7 @@ func (h *Handler) getGames(c echo.Context) error { } return c.Render(http.StatusOK, "games", echo.Map{ - "BasePath": basePath, + "BasePath": h.conf.BasePath, "Title": "Games", "Games": games, }) @@ -257,7 +255,7 @@ func (h *Handler) getGameEdit(c echo.Context) error { } return c.Render(http.StatusOK, "game_edit", echo.Map{ - "BasePath": basePath, + "BasePath": h.conf.BasePath, "Title": "Game Edit", "Game": echo.Map{ "GameID": row.GameID, @@ -367,7 +365,7 @@ func (h *Handler) postGameEdit(c echo.Context) error { } } - return c.Redirect(http.StatusSeeOther, basePath+"/admin/games") + return c.Redirect(http.StatusSeeOther, h.conf.BasePath+"admin/games") } func (h *Handler) postGameStart(c echo.Context) error { @@ -389,7 +387,7 @@ func (h *Handler) postGameStart(c echo.Context) error { return echo.NewHTTPError(http.StatusInternalServerError, err.Error()) } - return c.Redirect(http.StatusSeeOther, basePath+"/admin/games") + return c.Redirect(http.StatusSeeOther, h.conf.BasePath+"admin/games") } func (h *Handler) getOnlineQualifyingRanking(c echo.Context) error { @@ -424,7 +422,7 @@ func (h *Handler) getOnlineQualifyingRanking(c echo.Context) error { } } return c.Render(http.StatusOK, "online_qualifying_ranking", echo.Map{ - "BasePath": basePath, + "BasePath": h.conf.BasePath, "Title": "Online Qualifying Ranking", "Entries": entries, }) @@ -464,5 +462,5 @@ func (h *Handler) postFix(c echo.Context) error { return echo.NewHTTPError(http.StatusInternalServerError, err.Error()) } } - return c.Redirect(http.StatusSeeOther, basePath+"/admin/dashboard") + return c.Redirect(http.StatusSeeOther, h.conf.BasePath+"admin/dashboard") } diff --git a/backend/admin/templates/base.html b/backend/admin/templates/base.html index 08c7dc5..653acc6 100644 --- a/backend/admin/templates/base.html +++ b/backend/admin/templates/base.html @@ -2,9 +2,9 @@ <html> <head> <title>ADMIN {{ .Title }} | PHPerKaigi 2025 Albatross</title> - <link rel="icon" href="{{ .BasePath }}/favicon.svg"> - <link rel="stylesheet" href="{{ .BasePath }}/admin/css/normalize.css"> - <link rel="stylesheet" href="{{ .BasePath }}/admin/css/sakura.css"> + <link rel="icon" href="{{ .BasePath }}favicon.svg"> + <link rel="stylesheet" href="{{ .BasePath }}admin/css/normalize.css"> + <link rel="stylesheet" href="{{ .BasePath }}admin/css/sakura.css"> </head> <body> <section> diff --git a/backend/admin/templates/dashboard.html b/backend/admin/templates/dashboard.html index 92133b6..dcc71ba 100644 --- a/backend/admin/templates/dashboard.html +++ b/backend/admin/templates/dashboard.html @@ -2,18 +2,18 @@ {{ define "content" }} <p> - <a href="{{ .BasePath }}/admin/users">Users</a> + <a href="{{ .BasePath }}admin/users">Users</a> </p> <p> - <a href="{{ .BasePath }}/admin/games">Games</a> + <a href="{{ .BasePath }}admin/games">Games</a> </p> <p> - <a href="{{ .BasePath }}/admin/online-qualifying-ranking?game_1=7&game_2=8">Online Qualifying Ranking</a> + <a href="{{ .BasePath }}admin/online-qualifying-ranking?game_1=7&game_2=8">Online Qualifying Ranking</a> </p> -<form method="post" action="{{ .BasePath }}/admin/fix"> +<form method="post" action="{{ .BasePath }}admin/fix"> <button type="submit">fix</button> </form> -<form method="post" action="{{ .BasePath }}/logout"> +<form method="post" action="{{ .BasePath }}logout"> <button type="submit">Logout</button> </form> {{ end }} diff --git a/backend/admin/templates/game_edit.html b/backend/admin/templates/game_edit.html index 0d92c95..2d769c4 100644 --- a/backend/admin/templates/game_edit.html +++ b/backend/admin/templates/game_edit.html @@ -1,7 +1,7 @@ {{ template "base.html" . }} {{ define "breadcrumb" }} -<a href="{{ .BasePath }}/admin/dashboard">Dashboard</a> | <a href="{{ .BasePath }}/admin/games">Games</a> +<a href="{{ .BasePath }}admin/dashboard">Dashboard</a> | <a href="{{ .BasePath }}admin/games">Games</a> {{ end }} {{ define "content" }} @@ -59,7 +59,7 @@ <button type="submit">Save</button> </div> <div> - <button type="submit" formaction="{{ .BasePath }}/admin/games/{{ .Game.GameID }}/start">Start</button> + <button type="submit" formaction="{{ .BasePath }}admin/games/{{ .Game.GameID }}/start">Start</button> </div> </form> {{ end }} diff --git a/backend/admin/templates/games.html b/backend/admin/templates/games.html index 3be6726..b5c512a 100644 --- a/backend/admin/templates/games.html +++ b/backend/admin/templates/games.html @@ -1,7 +1,7 @@ {{ template "base.html" . }} {{ define "breadcrumb" }} -<a href="{{ .BasePath }}/admin/dashboard">Dashboard</a> +<a href="{{ .BasePath }}admin/dashboard">Dashboard</a> {{ end }} {{ define "content" }} diff --git a/backend/admin/templates/online_qualifying_ranking.html b/backend/admin/templates/online_qualifying_ranking.html index 039687e..663b68e 100644 --- a/backend/admin/templates/online_qualifying_ranking.html +++ b/backend/admin/templates/online_qualifying_ranking.html @@ -1,7 +1,7 @@ {{ template "base.html" . }} {{ define "breadcrumb" }} -<a href="{{ .BasePath }}/admin/dashboard">Dashboard</a> +<a href="{{ .BasePath }}admin/dashboard">Dashboard</a> {{ end }} {{ define "content" }} diff --git a/backend/admin/templates/user_edit.html b/backend/admin/templates/user_edit.html index 6942204..4c1016b 100644 --- a/backend/admin/templates/user_edit.html +++ b/backend/admin/templates/user_edit.html @@ -1,7 +1,7 @@ {{ template "base.html" . }} {{ define "breadcrumb" }} -<a href="{{ .BasePath }}/admin/dashboard">Dashboard</a> | <a href="{{ .BasePath }}/admin/users">Users</a> +<a href="{{ .BasePath }}admin/dashboard">Dashboard</a> | <a href="{{ .BasePath }}admin/users">Users</a> {{ end }} {{ define "content" }} diff --git a/backend/admin/templates/users.html b/backend/admin/templates/users.html index 36fae0d..4b8e6dc 100644 --- a/backend/admin/templates/users.html +++ b/backend/admin/templates/users.html @@ -1,7 +1,7 @@ {{ template "base.html" . }} {{ define "breadcrumb" }} -<a href="{{ .BasePath }}/admin/dashboard">Dashboard</a> +<a href="{{ .BasePath }}admin/dashboard">Dashboard</a> {{ end }} {{ define "content" }} diff --git a/backend/config.go b/backend/config/config.go index 99a6d54..8211bfd 100644 --- a/backend/config.go +++ b/backend/config/config.go @@ -1,4 +1,4 @@ -package main +package config import ( "fmt" @@ -6,12 +6,13 @@ import ( ) type Config struct { - dbHost string - dbPort string - dbUser string - dbPassword string - dbName string - isLocal bool + DBHost string + DBPort string + DBUser string + DBPassword string + DBName string + BasePath string + IsLocal bool } func NewConfigFromEnv() (*Config, error) { @@ -35,14 +36,19 @@ func NewConfigFromEnv() (*Config, error) { if !exists { return nil, fmt.Errorf("ALBATROSS_DB_NAME not set") } + basePath, exists := os.LookupEnv("ALBATROSS_BASE_PATH") + if !exists { + return nil, fmt.Errorf("ALBATROSS_BASE_PATH not set") + } isLocalStr, exists := os.LookupEnv("ALBATROSS_IS_LOCAL") isLocal := exists && isLocalStr == "1" return &Config{ - dbHost: dbHost, - dbPort: dbPort, - dbUser: dbUser, - dbPassword: dbPassword, - dbName: dbName, - isLocal: isLocal, + DBHost: dbHost, + DBPort: dbPort, + DBUser: dbUser, + DBPassword: dbPassword, + DBName: dbName, + BasePath: basePath, + IsLocal: isLocal, }, nil } diff --git a/backend/main.go b/backend/main.go index 06d37c3..c13dea4 100644 --- a/backend/main.go +++ b/backend/main.go @@ -13,6 +13,7 @@ import ( "github.com/nsfisis/phperkaigi-2025-albatross/backend/admin" "github.com/nsfisis/phperkaigi-2025-albatross/backend/api" + "github.com/nsfisis/phperkaigi-2025-albatross/backend/config" "github.com/nsfisis/phperkaigi-2025-albatross/backend/db" "github.com/nsfisis/phperkaigi-2025-albatross/backend/game" "github.com/nsfisis/phperkaigi-2025-albatross/backend/taskqueue" @@ -33,19 +34,19 @@ func connectDB(ctx context.Context, dsn string) (*pgxpool.Pool, error) { func main() { var err error - config, err := NewConfigFromEnv() + conf, err := config.NewConfigFromEnv() if err != nil { log.Fatalf("Error loading env %v", err) } - openAPISpec, err := api.GetSwaggerWithPrefix("/phperkaigi/2025/code-battle/api") + openAPISpec, err := api.GetSwaggerWithPrefix(conf.BasePath + "api") if err != nil { log.Fatalf("Error loading OpenAPI spec\n: %s", err) } ctx := context.Background() - dbDSN := fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s sslmode=disable", config.dbHost, config.dbPort, config.dbUser, config.dbPassword, config.dbName) + dbDSN := fmt.Sprintf("host=%s port=%s user=%s password=%s dbname=%s sslmode=disable", conf.DBHost, conf.DBPort, conf.DBUser, conf.DBPassword, conf.DBName) connPool, err := connectDB(ctx, dbDSN) if err != nil { log.Fatalf("Error connecting to db %v", err) @@ -65,27 +66,27 @@ func main() { gameHub := game.NewGameHub(queries, taskQueue, workerServer) - apiGroup := e.Group("/phperkaigi/2025/code-battle/api") + apiGroup := e.Group(conf.BasePath + "api") apiGroup.Use(oapimiddleware.OapiRequestValidator(openAPISpec)) apiHandler := api.NewHandler(queries, gameHub) api.RegisterHandlers(apiGroup, api.NewStrictHandler(apiHandler, nil)) - adminHandler := admin.NewHandler(queries) - adminGroup := e.Group("/phperkaigi/2025/code-battle/admin") + adminHandler := admin.NewHandler(queries, conf) + adminGroup := e.Group(conf.BasePath + "admin") adminHandler.RegisterHandlers(adminGroup) - if config.isLocal { - filesGroup := e.Group("/phperkaigi/2025/code-battle/files") + if conf.IsLocal { + filesGroup := e.Group(conf.BasePath + "files") filesGroup.Use(middleware.StaticWithConfig(middleware.StaticConfig{ Root: "/", Filesystem: http.Dir("/data/files"), IgnoreBase: true, })) - e.GET("/phperkaigi/2025/code-battle/*", func(c echo.Context) error { + e.GET(conf.BasePath+"*", func(c echo.Context) error { return c.Redirect(http.StatusPermanentRedirect, "http://localhost:5173"+c.Request().URL.Path) }) - e.POST("/phperkaigi/2025/code-battle/*", func(c echo.Context) error { + e.POST(conf.BasePath+"*", func(c echo.Context) error { return c.Redirect(http.StatusPermanentRedirect, "http://localhost:5173"+c.Request().URL.Path) }) diff --git a/compose.prod.yaml b/compose.prod.yaml index 1da939b..5e12083 100644 --- a/compose.prod.yaml +++ b/compose.prod.yaml @@ -37,6 +37,7 @@ services: context: ./frontend args: ALBATROSS_HOST: localhost + ALBATROSS_BASE_PATH: $ALBATROSS_BASE_PATH expose: - 80 env_file: [.env] diff --git a/docs/DEV.md b/docs/DEV.md index 7f79840..2a44f4a 100644 --- a/docs/DEV.md +++ b/docs/DEV.md @@ -18,6 +18,9 @@ 1. Clone the repository. 1. `cd path/to/the/repo` +1. Copy `.env.example` to `.env` and configure: + * `ALBATROSS_JWT_SECRET`: Secret key for JWT tokens + * `ALBATROSS_COOKIE_SECRET`: Secret key for cookies 1. `make init` 1. `make up` 1. Access to http://localhost:5173/phperkaigi/2025/code-battle/. diff --git a/frontend/Dockerfile b/frontend/Dockerfile index 0e6499c..2659296 100644 --- a/frontend/Dockerfile +++ b/frontend/Dockerfile @@ -1,4 +1,5 @@ ARG ALBATROSS_HOST +ARG ALBATROSS_BASE_PATH FROM node:22.14 AS builder @@ -9,6 +10,7 @@ COPY package.json package-lock.json . RUN npm install --include=dev COPY . . +ENV ALBATROSS_BASE_PATH="$ALBATROSS_BASE_PATH" RUN npm run build ################################################################################ diff --git a/frontend/app/api/client.ts b/frontend/app/api/client.ts index ee5437d..6fa784f 100644 --- a/frontend/app/api/client.ts +++ b/frontend/app/api/client.ts @@ -1,12 +1,13 @@ import createClient from "openapi-fetch"; import { createContext } from "react"; +import { API_BASE_PATH } from "../config"; import type { paths } from "./schema"; const client = createClient<paths>({ baseUrl: process.env.NODE_ENV === "development" - ? "http://localhost:8003/phperkaigi/2025/code-battle/api/" - : "https://t.nil.ninja/phperkaigi/2025/code-battle/api/", + ? `http://localhost:8003${API_BASE_PATH}` + : `https://t.nil.ninja${API_BASE_PATH}`, }); export async function apiLogin(username: string, password: string) { diff --git a/frontend/app/components/UserIcon.tsx b/frontend/app/components/UserIcon.tsx index e14a571..8002c6f 100644 --- a/frontend/app/components/UserIcon.tsx +++ b/frontend/app/components/UserIcon.tsx @@ -1,3 +1,5 @@ +import { BASE_PATH } from "../config"; + type Props = { iconPath: string; displayName: string; @@ -9,8 +11,8 @@ export default function UserIcon({ iconPath, displayName, className }: Props) { <img src={ process.env.NODE_ENV === "development" - ? `http://localhost:8003/phperkaigi/2025/code-battle${iconPath}` - : `/phperkaigi/2025/code-battle${iconPath}` + ? `http://localhost:8003${BASE_PATH}${iconPath}` + : `${BASE_PATH}${iconPath}` } alt={`${displayName} のアイコン`} className={`rounded-full border-4 border-white ${className}`} diff --git a/frontend/app/config.ts b/frontend/app/config.ts new file mode 100644 index 0000000..3e6e642 --- /dev/null +++ b/frontend/app/config.ts @@ -0,0 +1,2 @@ +export const BASE_PATH = import.meta.env.VITE_ALBATROSS_BASE_PATH || "/"; +export const API_BASE_PATH = `${BASE_PATH}api/`; diff --git a/frontend/app/root.tsx b/frontend/app/root.tsx index f1b5c54..7d08061 100644 --- a/frontend/app/root.tsx +++ b/frontend/app/root.tsx @@ -4,11 +4,12 @@ import type { LinksFunction } from "react-router"; import { Links, Meta, Outlet, Scripts, ScrollRestoration } from "react-router"; import "./tailwind.css"; import "./shiki.css"; +import { BASE_PATH } from "./config"; config.autoAddCss = false; export const links: LinksFunction = () => [ - { rel: "icon", href: "/phperkaigi/2025/code-battle/favicon.svg" }, + { rel: "icon", href: `${BASE_PATH}code-battle/favicon.svg` }, ]; export function Layout({ children }: { children: React.ReactNode }) { diff --git a/frontend/app/routes/_index.tsx b/frontend/app/routes/_index.tsx index ef54c84..9767985 100644 --- a/frontend/app/routes/_index.tsx +++ b/frontend/app/routes/_index.tsx @@ -2,6 +2,7 @@ import type { LoaderFunctionArgs, MetaFunction } from "react-router"; import { ensureUserNotLoggedIn } from "../.server/auth"; import BorderedContainer from "../components/BorderedContainer"; import NavigateLink from "../components/NavigateLink"; +import { BASE_PATH } from "../config"; export const meta: MetaFunction = () => [ { title: "PHPerKaigi 2025 Albatross" }, @@ -16,7 +17,7 @@ export default function Index() { return ( <div className="min-h-screen bg-sky-600 flex flex-col items-center justify-center gap-y-6"> <img - src="/phperkaigi/2025/code-battle/logo.svg" + src={`${BASE_PATH}logo.svg`} alt="PHPerKaigi 2025" className="w-64 h-64" /> diff --git a/frontend/app/routes/dashboard.tsx b/frontend/app/routes/dashboard.tsx index b7bfb01..75e809b 100644 --- a/frontend/app/routes/dashboard.tsx +++ b/frontend/app/routes/dashboard.tsx @@ -5,6 +5,7 @@ import { createApiClient } from "../api/client"; import BorderedContainerWithCaption from "../components/BorderedContainerWithCaption"; import NavigateLink from "../components/NavigateLink"; import UserIcon from "../components/UserIcon"; +import { BASE_PATH } from "../config"; export const meta: MetaFunction = () => [ { title: "Dashboard | PHPerKaigi 2025 Albatross" }, @@ -76,8 +77,8 @@ export default function Dashboard() { <a href={ process.env.NODE_ENV === "development" - ? "http://localhost:8003/phperkaigi/2025/code-battle/admin/dashboard" - : "/phperkaigi/2025/code-battle/admin/dashboard" + ? `http://localhost:8003${BASE_PATH}admin/dashboard` + : `${BASE_PATH}admin/dashboard` } className="text-lg text-white bg-sky-600 px-4 py-2 rounded-sm transition duration-300 hover:bg-sky-500 focus:ring-3 focus:ring-sky-400 focus:outline-hidden" > diff --git a/frontend/react-router.config.ts b/frontend/react-router.config.ts index cade2ea..10392e4 100644 --- a/frontend/react-router.config.ts +++ b/frontend/react-router.config.ts @@ -1,5 +1,5 @@ import type { Config } from "@react-router/dev/config"; export default { - basename: "/phperkaigi/2025/code-battle/", + basename: process.env.ALBATROSS_BASE_PATH || "/", } satisfies Config; diff --git a/frontend/vite.config.ts b/frontend/vite.config.ts index aab20f4..b9b2873 100644 --- a/frontend/vite.config.ts +++ b/frontend/vite.config.ts @@ -4,6 +4,6 @@ import { defineConfig } from "vite"; import tsconfigPaths from "vite-tsconfig-paths"; export default defineConfig({ - base: "/phperkaigi/2025/code-battle/", + base: process.env.ALBATROSS_BASE_PATH || "/", plugins: [tailwindcss(), reactRouter(), tsconfigPaths()], }); |
