Skip to content

Cookie settings

Choose which kinds of cookies you allow. You can change your choice at any time via Cookie settings at the bottom of every page. Privacy statement

Necessary

Always on

Needed to log in, keep your cart and remember your choices. These are always on.

Which cookies?
  • weboke_sessie, weboke_klant, weboke_remember: your session and staying logged in
  • weboke_basket: your cart
  • wkBtwIncl: showing prices with or without VAT
  • wok_cookies: your cookie choice, 12 months

Measures which ad leads to a visit or order, so we do not pay for ads that do nothing.

Which cookies?
  • Google Ads via Google Tag Manager (_gcl_au, _gcl_aw), up to 90 days
  • OpenAI Ads, ads in ChatGPT
  • wok_aff: which partner referred you to us (affiliate programme), 60 days

4.6

Country and language

Each country has its own site, with prices and VAT for that country.

View

Putting your app from Lovable, Bolt or another AI builder on your WebOké hosting

Built an app with Lovable, Bolt or another AI builder and want to put it on your own domain at WebOké? You can. This article explains how to get the code out of the AI builder, how to build and upload the app, and how GitHub can do that for you automatically.

First check what kind of app you have. That determines whether you only need to upload files, or whether your app needs its own Node.js server.

1. What kind of app do you have?

Open the package.json file in your project. It tells you what kind of app it is.

  • A static app (React with Vite). package.json contains vite and no server framework. Running npm run build creates a dist folder with plain HTML, JavaScript and CSS files. You upload those to public_html. This works on any hosting plan. Many apps from Bolt and older apps from Lovable are built this way.
  • An app with its own server. Since 13 May 2026, Lovable builds apps with TanStack Start: in that case package.json contains @tanstack/react-start. Such an app runs server code, so it won't work as loose files in public_html. You set it up as a Node.js app (see step 6). The same applies to other apps with their own server, such as an Express backend.
  • An app with Supabase or Lovable Cloud as its backend. The database, login and functions stay with Supabase or Lovable. On WebOké you only host the front end. When building, you do need to pass in the Supabase URL and public key (see step 5).

2. Getting the code out of the AI builder via GitHub

Lovable and Bolt can put your project in your own GitHub repository. Changes then sync both ways: what you change in the AI builder ends up in GitHub, and what you change in GitHub comes back into the AI builder.

In Lovable:

  1. Open your project and go to Project settings > Git > GitHub.
  2. Click Add connection and give the Lovable app access to your GitHub account.
  3. Under Accounts, click Connect. Lovable creates a private repository and keeps it up to date.

You can also do it without GitHub: use Download codebase under Project settings > Git to download the code (on a paid Lovable plan).

In Bolt:

  1. Open your project and click the GitHub icon in the top right.
  2. Log in to GitHub, click Authorize and install Bolt's GitHub app.
  3. Enter a name for the repository and click Create repository. Bolt then works in the main branch.

3. Building and uploading a static app

You build the app on your own computer. For that you need Node.js, version 22 (the current Vite requires at least 20.19 or 22.12).

  1. Get the code: git clone your repository, or unzip the download.
  2. Open a terminal in the project folder and install the packages with npm ci (or npm install if there's no package-lock.json).
  3. Build the app with npm run build. You now have a dist folder containing an index.html and an assets folder.
  4. Upload the contents of dist to domains/yourdomain.nl/public_html, using an FTP client or the File Manager in DirectAdmin. So don't upload the dist folder itself, and don't upload the source code or node_modules.
  5. Place the .htaccess file below in public_html.

An app with multiple pages (a router) shows addresses in the browser like yourdomain.nl/about-us. Those pages don't exist as files on the server. If you refresh such a page or open the link directly, you get a 404. With this .htaccess file, the server sends those addresses to index.html, and the app then shows the right page:

RewriteEngine On
RewriteBase /
RewriteCond %{REQUEST_FILENAME} -f [OR]
RewriteCond %{REQUEST_FILENAME} -d
RewriteRule ^ - [L]
RewriteRule ^assets/ - [R=404,L]
RewriteRule ^ index.html [L]

Existing files and folders are simply served by the server. A missing file in assets returns a real 404, so errors are easier to spot. Everything else goes to the app.

Put the .htaccess file in your project's public folder. Vite copies everything from public to dist on every build, so it always gets uploaded along with the rest. Can't see the file in your FTP client or File Manager? Files starting with a dot are sometimes hidden, see Showing and editing hidden files such as .htaccess.

4. Putting the app in a subfolder

Want the app at yourdomain.nl/app instead of yourdomain.nl? Then the app needs to know that at build time. Otherwise the browser looks for the files in /assets instead of /app/assets and the screen stays white.

  1. In vite.config.js (or vite.config.ts), set the option base: '/app/'.
  2. Give the router the same path. With React Router, you do this with <BrowserRouter basename={import.meta.env.BASE_URL}>.
  3. Build again and upload the contents of dist to public_html/app.
  4. In public_html/app/.htaccess, place the same file as above, with RewriteBase /app/.

5. Supabase, Lovable Cloud and other settings (env variables)

Settings that start with VITE_, such as VITE_SUPABASE_URL and VITE_SUPABASE_PUBLISHABLE_KEY (VITE_SUPABASE_ANON_KEY in older projects), are written into the JavaScript files by Vite during the build. You can't set them on the server afterwards.

  • You'll find the values in your project's .env file. Copy the names exactly as they are.
  • If your project has no .env file, create one yourself in the project folder before you run npm run build. With GitHub Actions, you set them as secrets (see step 7).
  • If you've changed a value, rebuild and re-upload the app.
Anything with VITE_ can be read by every visitor. Supabase's public key (publishable or anon key) is fine there, as that's what it's meant for; Supabase protects your data with security rules (row level security). Never put the service_role key or any other secret key in a VITE_ variable.

6. An app with its own server: as a Node.js app

You set up an app with server code, such as a TanStack Start app from Lovable, using Setup Node.js App in DirectAdmin. You can read how that works in Activating Node.js in DirectAdmin. For a TanStack Start app, it goes like this:

  1. Build the app on your computer with NITRO_PRESET=node-server npm run build. You'll now have a .output folder.
  2. Create an app under Setup Node.js App, with Node.js 22 and a folder outside public_html, for example apps/myapp.
  3. Upload the .output folder to that folder.
  4. In the same folder, create a file start.cjs containing this single line, and enter start.cjs under Application startup file:
    import('./.output/server/index.mjs');
  5. Add the settings the server needs, such as SUPABASE_URL and SUPABASE_PUBLISHABLE_KEY, under Environment variables.
  6. Click Restart. Do this after every new upload as well.

The small start.cjs file is needed because the server in .output is a modern JavaScript module (.mjs), while the Node.js environment loads the startup file the old way. If the app returns a 503 error, check stderr.log in your app's folder.

7. Automatic deployment with GitHub Actions

With GitHub Actions, GitHub builds your app on every change to the main branch and puts the result on your package. Because Lovable and Bolt write to GitHub, a change from the AI builder is then online within a few minutes. The Git feature in DirectAdmin doesn't build anything; it only places files. That's why GitHub Actions is more convenient for a Vite app.

Never put passwords and keys in your repository; store them as a secret in GitHub instead:

  1. Open your repository on GitHub and go to Settings > Secrets and variables > Actions.
  2. Click New repository secret, enter the name and the value and click Add secret. Do this for each secret from the variant you choose.
  3. Create the file .github/workflows/deploy.yml in your repository with one of the two examples below.
  4. After the next change, check the Actions tab to see whether it worked. You can also start it manually with Run workflow.

Variant A: via FTPS (all hosting packages). In DirectAdmin, create a separate FTP account for GitHub, with the Domain option selected under Root folder (see How does FTP work at WebOké?). Secrets: FTP_SERVER (the server name of your package, such as linux2023.webawere.nl, not your domain name), FTP_USERNAME (the full name, such as github@yourdomain.nl), FTP_PASSWORD, and your app's VITE_ values.

name: Build and deploy

on:
  push:
    branches: [main]
  workflow_dispatch:

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-node@v7
        with:
          node-version: 22
          cache: npm
      - run: npm ci
      - run: npm run build
        env:
          VITE_SUPABASE_URL: ${{ secrets.VITE_SUPABASE_URL }}
          VITE_SUPABASE_PUBLISHABLE_KEY: ${{ secrets.VITE_SUPABASE_PUBLISHABLE_KEY }}
      - uses: SamKirkland/FTP-Deploy-Action@v4.4.0
        with:
          server: ${{ secrets.FTP_SERVER }}
          username: ${{ secrets.FTP_USERNAME }}
          password: ${{ secrets.FTP_PASSWORD }}
          protocol: ftps
          port: 21
          local-dir: ./dist/
          server-dir: public_html/

Variant B: via SSH with rsync (packages with SSH). SSH is included in Power Webhost Three and Four, AI Wordpress Three and Power Reseller, on port 1967 and with a key only (see SSH access and the Terminal in DirectAdmin).

  1. On your computer, create a separate key for GitHub, without a passphrase: ssh-keygen -t ed25519 -f github-deploy -N "".
  2. Paste the contents of github-deploy.pub in DirectAdmin under SSH Keys > PASTE KEY.
  3. Put the contents of github-deploy (the private key) in the secret SSH_PRIVATE_KEY. Then delete the file from your computer.
  4. Run ssh-keyscan -p 1967 linux2023.webawere.nl and put the output in the secret SSH_KNOWN_HOSTS. This way GitHub checks that it's really connecting to your server.
  5. Also add SSH_HOST (the server name), SSH_USER (your DA username), DOMEIN (such as yourdomain.nl) and the VITE_ values as secrets.
name: Build and deploy

on:
  push:
    branches: [main]
  workflow_dispatch:

jobs:
  deploy:
    runs-on: ubuntu-latest
    steps:
      - uses: actions/checkout@v7
      - uses: actions/setup-node@v7
        with:
          node-version: 22
          cache: npm
      - run: npm ci
      - run: npm run build
        env:
          VITE_SUPABASE_URL: ${{ secrets.VITE_SUPABASE_URL }}
          VITE_SUPABASE_PUBLISHABLE_KEY: ${{ secrets.VITE_SUPABASE_PUBLISHABLE_KEY }}
      - name: Deploy
        env:
          SSH_KEY: ${{ secrets.SSH_PRIVATE_KEY }}
          SSH_KNOWN_HOSTS: ${{ secrets.SSH_KNOWN_HOSTS }}
          SSH_HOST: ${{ secrets.SSH_HOST }}
          SSH_USER: ${{ secrets.SSH_USER }}
          DOMEIN: ${{ secrets.DOMEIN }}
        run: |
          mkdir -p ~/.ssh
          printf '%s\n' "$SSH_KEY" > ~/.ssh/deploy_key
          chmod 600 ~/.ssh/deploy_key
          printf '%s\n' "$SSH_KNOWN_HOSTS" > ~/.ssh/known_hosts
          rsync -rlptz --delete --exclude=.well-known --exclude=cgi-bin \
            -e "ssh -p 1967 -i ~/.ssh/deploy_key" \
            dist/ "$SSH_USER@$SSH_HOST:domains/$DOMEIN/public_html/"
Because of --delete, rsync removes everything from public_html that isn't part of your app, except .well-known (needed for your SSL certificate) and cgi-bin. If there's anything else in public_html, such as a second site in a subfolder, remove --delete or put the app in its own subfolder.

If you don't use Supabase, leave out the lines with VITE_SUPABASE or replace them with your own app's VITE_ variables. If logging in fails a few times, the server temporarily blocks GitHub's IP address. In that case, check your secrets and start the workflow again.

8. Common errors

  • The homepage works, but refreshing or a direct link gives a 404. The .htaccess file from step 3 is missing or is in the wrong folder.
  • A white screen. Open your browser's developer tools (F12) and check Console or Network. Do you see 404 errors on files in /assets? Then the path is wrong: you uploaded the dist folder itself instead of its contents, or the app is in a subfolder without the correct base (step 4).
  • The app loads, but logging in or data doesn't work, or you see a message such as supabaseUrl is required. The VITE_ variables weren't available during the build. Put them in .env or add them as a secret and build again.
  • The build fails with a message about the Node.js version. Use Node.js 22, both on your computer and in the workflow (node-version: 22).
  • npm ci fails. There is no package-lock.json, for example because the project only has a bun.lock. Run npm install once and add the new package-lock.json to your repository.
  • There is no index.html in the build. Then it's an app with its own server, such as TanStack Start. Set it up as a Node.js app (step 6).

See also: Connecting with FileZilla (FTP, FTPS and SFTP) and SSH keys and logging in with SSH.

Detailed explanation with screenshots: Setting up a Node.js app in the DirectAdmin manual.

Was this article helpful?

← Back to General hosting

One moment…

Set up your domains

For each domain, arrange the nameservers, the link to your hosting and who becomes the owner.

Loading your domains…