Storefront repo
Clone the GitHub repo behind a Behio hosted storefront, run it locally and deploy by pushing
Every website Behio hosts for a shop lives in its own private GitHub repository
under the Behio-Storefronts organisation, generated from a storefront template.
It is a plain Next.js 16 app wired to @behio/storefront-sdk, so you can clone it,
work on it locally and deploy by pushing.
Nothing of Behio's own source is in there. The repository holds only that one storefront.
All you need is a terminal and Node 22.
1. Get your commands from the admin
In the admin go to E-shop → Storefront, click Spravovat on the site you want and open the Lokální vývoj section. Vygenerovat přístupy a příkazy mints two things at once and renders the whole walkthrough as finished commands with your own values already in them:
- a deploy key registered on this one repository only, with read and write access, so you can clone and push with it,
- a public API key (
pk_live_...) for the shop, which is what the site reads its products with.
Neither is stored in plaintext on our side, so both are shown exactly once, right after you generate. Generating again rotates the deploy key: the previous one is removed from the repository and stops working immediately.
Copy each block from the admin in order and paste it into a terminal. The sections below explain what those blocks do and why they look the way they do. Nothing here needs to be filled in by hand.
2. Save the deploy key
mkdir -p ~/.ssh
cat > ~/.ssh/behio_<repo> <<'BEHIO_KEY'
-----BEGIN RSA PRIVATE KEY-----
...
-----END RSA PRIVATE KEY-----
BEHIO_KEY
chmod 600 ~/.ssh/behio_<repo>The heredoc delimiter is quoted (<<'BEHIO_KEY') so the shell leaves the key
untouched, and a heredoc always writes the trailing newline that ssh demands.
Without it ssh reports Load key: invalid format. The file is named after the
repository so a merchant with several sites does not overwrite one key with the next.
3. Clone
git clone -b <branch> -c core.sshCommand="ssh -i ~/.ssh/behio_<repo> -o IdentitiesOnly=yes" [email protected]:Behio-Storefronts/<repo>.git
cd <repo>-c core.sshCommand both authenticates this clone and persists into the new repo's
.git/config, so every later git push uses the deploy key without you thinking
about it.
Use core.sshCommand, not a Host github.com entry in ~/.ssh/config. A deploy
key authorises a single repository. An ~/.ssh/config entry keyed on github.com
applies to every GitHub remote on your machine, so ssh would offer the deploy key
for your other projects and GitHub would answer Repository not found.
IdentitiesOnly=yes matters for the same reason in reverse: without it ssh first
offers the keys already loaded in your agent, GitHub authenticates you as whoever
that key belongs to, and the clone fails even though the deploy key is correct.
-b <branch> checks out the branch your site actually runs from (see section 5).
Without it the clone lands on main, and on a preview site behio-draft is normally
ahead of main, so your first push would be rejected as a non-fast-forward.
4. Write .env and run it
cat > .env <<'BEHIO_ENV'
BEHIO_API_KEY="pk_live_..."
NEXT_PUBLIC_BEHIO_API_KEY="pk_live_..."
BEHIO_API_URL="https://be.behio.com"
NEXT_PUBLIC_BEHIO_API_URL="https://be.behio.com"
NEXT_PUBLIC_SITE_URL="http://localhost:7010"
BEHIO_STOREFRONT_NOINDEX="1"
BEHIO_ENVnpm install --no-package-lock
npm run devThe dev server listens on http://localhost:7010 and serves your shop's real data.
When something is wrong, the terminal says so. Storefronts generated from
2026-07-29 on print the reason into the terminal running npm run dev, and show it
in a banner at the bottom of the page, in Czech: no API key in .env, a key the
server rejected (401), an unreachable API, or a shop that is simply not launched
yet. The banner exists only under npm run dev; a deployed site never renders it.
Older repositories print nothing, which is why the .env block above matters:
copy it whole, as printed.
| Variable | Why |
|---|---|
BEHIO_API_KEY | The shop's public API key. Server side reads and server actions. |
NEXT_PUBLIC_BEHIO_API_KEY | The same key. It ships in the browser bundle and drives the client hooks. |
BEHIO_API_URL / NEXT_PUBLIC_BEHIO_API_URL | The backend. Same value the deploy pipeline sets on the hosted app. |
NEXT_PUBLIC_SITE_URL | http://localhost:7010 locally. Canonical origin for SEO. |
BEHIO_STOREFRONT_NOINDEX | Marks the run as not a public production site, exactly like the sandbox application. Without it a shop you have not launched yet (Aktivní switched off) renders the maintenance page Připravujeme se instead of your site, and nothing anywhere says why. |
Both key variables get the same public key on purpose. That is exactly what the deploy pipeline sets on the hosted app, so a local run sees the same data as production. A public key is publishable by design: the deployed site already ships that value in its browser bundle.
npm, not yarn. The template's package.json only defines plain next scripts and
ships no lockfile, so npm resolves exactly the way the production Docker image does
(it runs npm install too). --no-package-lock matters because the push step below
is git add -A: a lockfile written here would land in your repository and pin
@behio/storefront-sdk, which package.json deliberately floats as "*" so every
build picks up the current SDK.
.env and .env.local are gitignored and the Docker build ignores them too, so
they never reach the deployed site.
5. Push, and what a push deploys
A storefront can run as two applications from the same repository:
| Branch | Application | Address |
|---|---|---|
main | production site | the custom domain, or <slug>.behio.com |
behio-draft | sandbox preview | <slug>-sandbox.behio.com |
A push deploys on its own. Pushing to a branch rebuilds and redeploys the application that serves it, with nothing to click in the admin. It usually takes a minute or two. There is no webhook for you to set up: our GitHub organisation app forwards the push, and the deploy pipeline keeps auto deploy switched on for every application it provisions.
The catch is that this only works for a branch that has an application behind
it. A shop that has never published a production site has no main application,
only the sandbox, and a push to main there succeeds in git and deploys nothing,
silently. This is why the clone in section 3 checks out the site's own branch and
why the Lokální vývoj panel prints the push command for that branch: copy it
from there rather than guessing.
npm run build # a build that fails is never deployed
git add -A
git commit -m "uprava webu"
git push origin HEAD:behio-draft # sandbox, every shop has this one
git push origin HEAD:main # production, only once the shop is liveThe build runs on Behio's infrastructure: npm install plus next build inside
Docker, served with next start on port 3000 behind our proxy.
Feedback is coarse today. There is no build log in the admin and no progress bar. The site status shown in the admin tracks only the deploys started from the admin, so it stays on its previous value through a push triggered build even while the site is being rebuilt: check the site itself for the result. Use Přepublikovat in the same panel when you want a deploy whose status is reported back in the admin.
6. What else writes to your repository
The AI site editor in the admin commits to the same repository:
- AI edits are committed to
behio-draft, - Publikovat merges
behio-draftintomainand deploys, - Vrátit and Vrátit publikaci move the branch by force to an older commit.
A force move can drop commits you pushed. Pull before you start, push finished work promptly, and do not run the AI editor on a site while you are working on its repository.
The deploy pipeline itself does not rewrite your files. Runtime configuration
(BEHIO_API_KEY, NEXT_PUBLIC_SITE_URL, indexing flags) is set on the hosted
application on every deploy, not in the repository, so committing an .env changes
nothing about the live site.
Keep the repository root layout intact: the build expects Dockerfile at the root
and an app that listens on port 3000 in production.
Troubleshooting
| Symptom | Cause |
|---|---|
| Locally you get Připravujeme se / Obchod je právě v údržbě instead of the shop | The shop is not launched yet (Aktivní off), and the local run was missing BEHIO_STOREFRONT_NOINDEX="1", which is what tells the site it is not a public production deployment. Add that line to .env and restart. Nothing is wrong with your key or your repository. |
| The site loads but is called Store and has no products | The API key was rejected or the API was unreachable. Read the terminal running npm run dev: it names which of the two happened. Most often the key was rotated in the admin, or only its shortened preview was pasted instead of the full pk_live_... value. |
Missing API key. Set BEHIO_API_KEY env var | There is no .env in the project root, or BEHIO_API_KEY in it is empty. The file must sit next to package.json and be named .env. |
ERROR: Repository not found on clone | ssh authenticated with another key. Add -o IdentitiesOnly=yes and point -i at the deploy key. |
Permission denied (publickey) | Wrong path in -i, or the key was rotated in the admin and the old one no longer works. |
Load key ...: invalid format | The key file lost its trailing newline, or chmod 600 is missing. Paste the block from the admin unchanged, the heredoc handles both. |
! [rejected] ... non-fast-forward on push | You are on main but pushing to behio-draft, which is ahead. Clone with -b behio-draft, or git pull first. |
| Push succeeded, site unchanged | You pushed a branch with no application behind it, almost always main on a shop that is not live yet. Use the push command printed in the Lokální vývoj panel. |
| Push deployed, but the admin still shows the old status | Expected. The status follows admin triggered deploys only. Look at the site, or redeploy with Přepublikovat. |
Status went to Selhalo | The build failed. Reproduce with npm run build locally; the deployment log is not exposed in the admin yet. |