mirror of
https://github.com/formbricks/formbricks.git
synced 2025-12-22 06:00:51 -06:00
Compare commits
7 Commits
docs/custo
...
release/4.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5c7867ccd1 | ||
|
|
39499ffb95 | ||
|
|
06beb30bb2 | ||
|
|
b8b5d320bc | ||
|
|
1f0042b55c | ||
|
|
eb14cc0593 | ||
|
|
b64beb83ad |
@@ -133,13 +133,16 @@ export const BlockCard = ({
|
||||
// A button label is invalid if it exists but doesn't have valid text for all enabled languages
|
||||
const surveyLanguages = localSurvey.languages ?? [];
|
||||
const hasInvalidButtonLabel =
|
||||
block.buttonLabel !== undefined && !isLabelValidForAllLanguages(block.buttonLabel, surveyLanguages);
|
||||
block.buttonLabel !== undefined &&
|
||||
block.buttonLabel["default"]?.trim() !== "" &&
|
||||
!isLabelValidForAllLanguages(block.buttonLabel, surveyLanguages);
|
||||
|
||||
// Check if back button label is invalid
|
||||
// Back button label should exist for all blocks except the first one
|
||||
const hasInvalidBackButtonLabel =
|
||||
blockIdx > 0 &&
|
||||
block.backButtonLabel !== undefined &&
|
||||
block.backButtonLabel["default"]?.trim() !== "" &&
|
||||
!isLabelValidForAllLanguages(block.backButtonLabel, surveyLanguages);
|
||||
|
||||
// Block should be highlighted if it has invalid elements OR invalid button labels
|
||||
|
||||
@@ -513,8 +513,8 @@ export const ElementsView = ({
|
||||
id: newBlockId,
|
||||
name: getBlockName(index ?? prevSurvey.blocks.length),
|
||||
elements: [{ ...updatedElement, isDraft: true }],
|
||||
buttonLabel: createI18nString(t("templates.next"), []),
|
||||
backButtonLabel: createI18nString(t("templates.back"), []),
|
||||
buttonLabel: createI18nString("", []),
|
||||
backButtonLabel: createI18nString("", []),
|
||||
};
|
||||
|
||||
return {
|
||||
|
||||
@@ -101,7 +101,7 @@
|
||||
"lucide-react": "0.507.0",
|
||||
"markdown-it": "14.1.0",
|
||||
"mime-types": "3.0.1",
|
||||
"next": "15.5.6",
|
||||
"next": "15.5.9",
|
||||
"next-auth": "4.24.12",
|
||||
"next-safe-action": "7.10.8",
|
||||
"node-fetch": "3.3.2",
|
||||
|
||||
@@ -232,7 +232,7 @@ test.describe("Survey Create & Submit Response without logic", async () => {
|
||||
for (let i = 0; i < surveys.createAndSubmit.ranking.choices.length; i++) {
|
||||
await page.getByText(surveys.createAndSubmit.ranking.choices[i]).click();
|
||||
}
|
||||
await page.locator("#questionCard-12").getByRole("button", { name: "Next" }).click();
|
||||
await page.locator("#questionCard-12").getByRole("button", { name: "Finish" }).click();
|
||||
// loading spinner -> wait for it to disappear
|
||||
await page.getByTestId("loading-spinner").waitFor({ state: "hidden" });
|
||||
});
|
||||
@@ -979,7 +979,7 @@ test.describe("Testing Survey with advanced logic", async () => {
|
||||
.fill("This is my city");
|
||||
await expect(page.getByLabel(surveys.createWithLogicAndSubmit.address.placeholder.zip)).toBeVisible();
|
||||
await page.getByLabel(surveys.createWithLogicAndSubmit.address.placeholder.zip).fill("12345");
|
||||
await page.locator("#questionCard-13").getByRole("button", { name: "Next" }).click();
|
||||
await page.locator("#questionCard-13").getByRole("button", { name: "Finish" }).click();
|
||||
|
||||
// loading spinner -> wait for it to disappear
|
||||
await page.getByTestId("loading-spinner").waitFor({ state: "hidden" });
|
||||
|
||||
@@ -234,7 +234,6 @@
|
||||
"self-hosting/configuration/smtp",
|
||||
"self-hosting/configuration/file-uploads",
|
||||
"self-hosting/configuration/domain-configuration",
|
||||
"self-hosting/configuration/custom-subpath",
|
||||
{
|
||||
"group": "Auth & SSO",
|
||||
"icon": "lock",
|
||||
|
||||
@@ -1,90 +0,0 @@
|
||||
---
|
||||
title: "Custom Subpath"
|
||||
description: "Serve Formbricks from a custom URL prefix when you cannot expose it on the root domain."
|
||||
icon: "link"
|
||||
---
|
||||
|
||||
<Note>
|
||||
Custom subpath deployments are currently under internal review. If you need early access, please reach out via
|
||||
[GitHub Discussions](https://github.com/formbricks/formbricks/discussions).
|
||||
</Note>
|
||||
|
||||
### When to use a custom subpath
|
||||
|
||||
Use a custom subpath (also called a Next.js base path) when your reverse proxy reserves the root domain for another
|
||||
service, but you still want Formbricks to live under the same hostname—for example `https://example.com/feedback`.
|
||||
Support for a build-time `BASE_PATH` variable is available in the Formbricks web app so that all internal routes,
|
||||
assets, and sign-in redirects honor the prefix.
|
||||
|
||||
### Requirements and limitations
|
||||
|
||||
- `BASE_PATH` must be present during `pnpm build`; changing it afterward requires a rebuild.
|
||||
- Official Formbricks Docker images do **not** accept this flag for technical reasons, so you must build your own image.
|
||||
- All public URLs (`WEBAPP_URL`, `NEXTAUTH_URL`, webhook targets, OAuth callbacks, etc.) need the same prefix.
|
||||
- Your proxy must rewrite `/custom-path/*` to the Formbricks container while keeping the prefix visible to clients.
|
||||
|
||||
### Configure environment variables
|
||||
|
||||
Add the following variables to the environment you use for builds (local, CI, or Docker build args):
|
||||
|
||||
```bash
|
||||
BASE_PATH="/custom-path"
|
||||
WEBAPP_URL="https://yourdomain.com/custom-path"
|
||||
NEXTAUTH_URL="https://yourdomain.com/custom-path/api/auth"
|
||||
```
|
||||
|
||||
If you use email links, webhooks, or third-party OAuth providers, ensure every URL you register includes the prefix.
|
||||
|
||||
### Build a Docker image with a custom subpath
|
||||
|
||||
<Steps>
|
||||
<Step title="Clone Formbricks and prepare secrets">
|
||||
Make sure you have the repository checked out and create temporary files (or use <code>--secret</code>) for the
|
||||
required build-time secrets such as <code>DATABASE_URL</code>, <code>ENCRYPTION_KEY</code>, <code>REDIS_URL</code>,
|
||||
and optional telemetry tokens.
|
||||
</Step>
|
||||
<Step title="Pass BASE_PATH as a build argument">
|
||||
Use the Formbricks web Dockerfile and supply the custom subpath via <code>--build-arg</code>. Example:
|
||||
|
||||
```bash
|
||||
docker build \
|
||||
--progress=plain \
|
||||
--no-cache \
|
||||
--build-arg BASE_PATH=/custom-path \
|
||||
--secret id=database_url,src=<(printf "postgresql://user:password@localhost:5432/formbricks?schema=public") \
|
||||
--secret id=encryption_key,src=<(printf "your-32-character-encryption-key-here") \
|
||||
--secret id=redis_url,src=<(printf "redis://localhost:6379") \
|
||||
--secret id=sentry_auth_token,src=<(printf "") \
|
||||
-f apps/web/Dockerfile \
|
||||
-t formbricks-web \
|
||||
.
|
||||
```
|
||||
|
||||
During the build logs you should see <code>BASE PATH /custom-path</code>, confirming that Next.js picked up the
|
||||
prefix.
|
||||
</Step>
|
||||
<Step title="Run the container behind your proxy">
|
||||
Start the resulting image with the same runtime environment variables you normally use (database credentials,
|
||||
mailing provider, etc.). Point your reverse proxy so that <code>/custom-path</code> requests forward to
|
||||
<code>http://formbricks-web:3000/custom-path</code> without stripping the prefix.
|
||||
</Step>
|
||||
</Steps>
|
||||
|
||||
### Verify the deployment
|
||||
|
||||
1. Open `https://yourdomain.com/custom-path` and complete the onboarding flow.
|
||||
2. Create a survey and preview it—embedded scripts now load assets relative to the subpath.
|
||||
3. Sign out and confirm the login page still includes `/custom-path`.
|
||||
|
||||
### Troubleshooting checklist
|
||||
|
||||
- Confirm your build pipeline actually passes `BASE_PATH` (and, if needed, `WEBAPP_URL`/`NEXTAUTH_URL`) into the build
|
||||
stage—check CI logs for the `BASE PATH /your-prefix` line and make sure custom Dockerfiles or wrappers forward
|
||||
`--build-arg BASE_PATH=...` correctly.
|
||||
- If you cannot log in, double-check that `NEXTAUTH_URL` includes the prefix and uses the full route to the API as stated above. NextAuth rejects callbacks that do not
|
||||
match exactly.
|
||||
- Re-run the Docker build when changing `BASE_PATH`; simply editing the container environment is not sufficient.
|
||||
- Inspect your proxy configuration to ensure it does not rewrite paths internally (e.g., `strip_prefix` needs to stay
|
||||
disabled).
|
||||
- When in doubt, rebuild locally with `--progress=plain` and verify that the `BASE PATH` line reflects your prefix.
|
||||
|
||||
@@ -41,8 +41,8 @@
|
||||
"i18n:validate": "pnpm scan-translations"
|
||||
},
|
||||
"dependencies": {
|
||||
"react": "19.1.0",
|
||||
"react-dom": "19.1.0"
|
||||
"react": "19.1.4",
|
||||
"react-dom": "19.1.4"
|
||||
},
|
||||
"devDependencies": {
|
||||
"@azure/microsoft-playwright-testing": "1.0.0-beta.7",
|
||||
|
||||
@@ -263,7 +263,7 @@ export function MultipleChoiceMultiElement({
|
||||
<label
|
||||
tabIndex={isCurrent ? 0 : -1}
|
||||
className={labelClassName}
|
||||
onKeyDown={handleKeyDown(otherOption.id)}>
|
||||
onKeyDown={otherSelected ? undefined : handleKeyDown(otherOption.id)}>
|
||||
<span className="fb-flex fb-items-center fb-text-sm">
|
||||
<input
|
||||
type="checkbox"
|
||||
|
||||
@@ -1355,7 +1355,6 @@ export const ZSurvey = z
|
||||
}
|
||||
}
|
||||
|
||||
//only validate back button label for blocks other than the first one and if back button is not hidden
|
||||
if (
|
||||
!isBackButtonHidden &&
|
||||
blockIndex > 0 &&
|
||||
|
||||
1186
pnpm-lock.yaml
generated
1186
pnpm-lock.yaml
generated
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user