LogoTransi-Store
DocsAPI
PreiseLogin

Developer Guide

Self-host Transi-Store on your own infrastructure.

Self-Hosting Overview

Transi-Store is fully open-source and can be self-hosted on your own infrastructure. You get the same features as the cloud version, without any usage limits.

The application is a React Router v7 SSR application backed by PostgreSQL. The recommended way to run it is with Docker Compose.

Requirements

RequirementVersion
Docker24+
Docker Composev2+
RAM512 MB minimum
Disk1 GB minimum

You do not need Node.js or Yarn on the host machine — everything runs inside Docker.

At least one OAuth provider (Google or GitHub) must be configured for authentication.

Installation

1. Clone the repository

git clone https://github.com/transi-store/transi-store.git
cd transi-store

2. Configure environment variables

Copy the example environment file and fill in the required values:

cp .env.example .env

Open .env and configure at minimum:

# Required — generate with: openssl rand -hex 32
SESSION_SECRET=a-long-random-string

# Required — generate with: openssl rand -hex 32
ENCRYPTION_KEY=64-char-hex-string

# Required — at least one OAuth provider
GOOGLE_CLIENT_ID=your-google-client-id
GOOGLE_CLIENT_SECRET=your-google-client-secret

# Required — public URL used for OAuth redirect URIs
DOMAIN_ROOT=https://your-domain.com

Note: DATABASE_URL is pre-configured for the Docker Compose setup and does not need to change unless you use an external database.

3. Start the application

make setup   # First time only — installs dependencies and creates the database schema
make dev     # Development server at http://localhost:5173

For a production build:

make build   # Build the application
make up      # Start production Docker containers

Configuration

Environment variables

VariableRequiredDescription
SESSION_SECRETYesSecret used to sign session cookies
ENCRYPTION_KEYYes64-char hex key for encrypting API keys
DATABASE_URLYesPostgreSQL connection string
GOOGLE_CLIENT_IDAt least one providerGoogle OAuth client ID
GOOGLE_CLIENT_SECRETAt least one providerGoogle OAuth client secret
GITHUB_CLIENT_IDAt least one providerGitHub OAuth app client ID
GITHUB_CLIENT_SECRETAt least one providerGitHub OAuth app client secret
DOMAIN_ROOTYesPublic URL of your instance (used for OAuth redirect URIs)

Setting up OAuth providers

Google OAuth:

  1. Go to Google Cloud Console.
  2. Create a new OAuth 2.0 client ID (type: Web application).
  3. Add https://your-domain.com/auth/google/callback as an authorized redirect URI.
  4. Copy the Client ID and Client Secret to your .env file.

GitHub OAuth:

  1. Go to GitHub Developer Settings.
  2. Create a new OAuth App.
  3. Set the Authorization callback URL to https://your-domain.com/auth/github/callback.
  4. Copy the Client ID and generate a Client Secret for your .env file.

Running in Production

The repository ships with a production-ready docker-compose.yml. After configuring your .env file:

make up    # Start all services (app + PostgreSQL)
make logs  # Follow logs
make down  # Stop all services

The application listens on port 5173 by default. Use a reverse proxy (nginx, Caddy, Traefik) to expose it on port 443 with HTTPS.

Reverse proxy example (nginx)

server {
    listen 443 ssl;
    server_name transi.example.com;

    location / {
        proxy_pass http://localhost:5173;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-Proto https;
    }
}

Database management

make db-push    # Apply schema changes after updating to a new version
make db-studio  # Open Drizzle Studio GUI in your browser
make db-reset   # Warning: wipe and recreate the database (destructive!)

Upgrading: after pulling a new version, run make db-push to apply any schema changes before restarting.

CLI Tool

The @transi-store/cli package provides a command-line interface for syncing translations in CI/CD pipelines.

Installation

npm install -g @transi-store/cli
# or add to your project
npm install --save-dev @transi-store/cli

Configuration

Create a transi-store.config.json at the root of your project:

{
  "$schema": "https://unpkg.com/@transi-store/cli/schema.json",
  "org": "acme",
  "projects": [
    {
      "project": "webapp",
      "langs": ["en", "fr", "de"],
      "format": "json",
      "output": "./src/locales/<lang>/translations.json"
    }
  ]
}

Set the TRANSI_STORE_API_KEY environment variable with your API key, then run:

Downloading translations

# Download all translations using the config file
transi-store download:config

# Download for a specific branch
transi-store download:config --branch feature/my-feature

# Download for a single project/locale without a config file
transi-store download --org acme --project webapp --locale fr --output ./locales/fr.json

Git branch auto-detection: when --branch is not provided, the CLI automatically detects the current git branch and uses it. On main/master, no branch filter is applied (main translations are fetched).

Uploading translations

# Upload all translation files using the config file
transi-store upload:config

# Upload for a specific branch
transi-store upload:config --branch feature/my-feature

# Upload a single file without a config file
transi-store upload --org acme --project webapp --locale fr --input ./locales/fr.json

Git branch auto-detection: when --branch is not provided, the CLI automatically detects the current git branch and uses it. On main/master, no branch filter is applied (keys are uploaded to the main project).

Git optimization: upload:config also skips files that have not changed compared to the default branch (main/master) when running in a git repository, to avoid unnecessary API calls.

This is ideal for integrating into CI/CD — download translated strings at build time and upload new source strings after developers add them.