This is a Next.js project bootstrapped with create-next-app.
First, run the development server:
npm run dev
# or
yarn dev
# or
pnpm dev
# or
bun devOpen http://localhost:3000 with your browser to see the result.
You can start editing the page by modifying app/page.tsx. The page auto-updates as you edit the file.
This project uses next/font to automatically optimize and load Geist, a new font family for Vercel.
To learn more about Next.js, take a look at the following resources:
- Next.js Documentation - learn about Next.js features and API.
- Learn Next.js - an interactive Next.js tutorial.
You can check out the Next.js GitHub repository - your feedback and contributions are welcome!
This app can send the currently edited translation file to another Next.js app using a server-side POST proxy.
Create .env.local in this project (you can copy from .env.example):
UAT_TARGET_URL=https://your-uat-app.example.com/api/translations/import
UAT_SHARED_SECRET=change-me-in-uat
UAT_CLIENT_ID=json-translatorAfter setting envs, restart the dev server.
When you click Wyślij do UAT, this app calls app/api/uat/push/route.ts, which forwards JSON to UAT_TARGET_URL with headers:
Authorization: Bearer <UAT_SHARED_SECRET>x-client-id: <UAT_CLIENT_ID>
Body:
{
"name": "translations.json",
"translations": { "home.title": "Witaj" },
"keys_count": 1
}Create endpoint app/api/translations/import/route.ts in the other project:
import { NextResponse } from "next/server";
export const runtime = "nodejs";
type ImportBody = {
name?: string;
translations?: Record<string, string>;
keys_count?: number;
};
export async function POST(request: Request) {
const expectedSecret = process.env.UAT_SHARED_SECRET;
const auth = request.headers.get("authorization");
if (!expectedSecret || auth !== `Bearer ${expectedSecret}`) {
return NextResponse.json({ error: "Unauthorized" }, { status: 401 });
}
const body = (await request.json()) as ImportBody;
if (!body.name || !body.translations || typeof body.keys_count !== "number") {
return NextResponse.json({ error: "Invalid payload" }, { status: 400 });
}
// TODO: save body.translations in your UAT app storage.
// Example: write to DB/file and optionally keep body.name metadata.
return NextResponse.json({ ok: true });
}In the second app set .env.local:
UAT_SHARED_SECRET=change-me-in-uat- Keep both apps behind HTTPS.
- Use a long random
UAT_SHARED_SECRET. - Optionally check
x-client-idagainst an allow-list. - Add simple rate-limit on the receiver endpoint.
The easiest way to deploy your Next.js app is to use the Vercel Platform from the creators of Next.js.
Check out our Next.js deployment documentation for more details.
This repository includes production Docker setup for Next.js with SQLite persistence.
- Create Docker env file:
cp .env.docker.example .env.docker-
Fill values in
.env.docker(at minimum:UAT_TARGET_URL,UAT_SHARED_SECRET). -
Build and start container:
docker compose up -d --buildApp will be available on http://localhost:3001.
- Host port is
3001to avoid conflict with an existing app on port3000. - SQLite file persists on host in
./data/translations.dbvia mounted volume./data:/app/data.
If you previously started the container with stricter file permissions and see SQLITE_READONLY, fix host directory permissions once:
sudo mkdir -p data
sudo chmod 0777 dataTo stop:
docker compose down