diff --git a/apps/compliance-portal/.env.example b/apps/compliance-portal/.env.example
new file mode 100644
index 000000000..460e575be
--- /dev/null
+++ b/apps/compliance-portal/.env.example
@@ -0,0 +1 @@
+VITE_API_URL=http://localhost:8080
diff --git a/apps/compliance-portal/.gitattributes b/apps/compliance-portal/.gitattributes
new file mode 100644
index 000000000..7a1fb9a7a
--- /dev/null
+++ b/apps/compliance-portal/.gitattributes
@@ -0,0 +1,2 @@
+__generated__/*.graphql linguist-generated
+__generated__/*.js linguist-generated
diff --git a/apps/compliance-portal/.gitignore b/apps/compliance-portal/.gitignore
new file mode 100644
index 000000000..b403dd978
--- /dev/null
+++ b/apps/compliance-portal/.gitignore
@@ -0,0 +1,26 @@
+public/pdfjs
+# Logs
+old
+logs
+*.log
+npm-debug.log*
+yarn-debug.log*
+yarn-error.log*
+pnpm-debug.log*
+lerna-debug.log*
+
+node_modules
+dist
+dist-ssr
+*.local
+
+# Editor directories and files
+.vscode/*
+!.vscode/extensions.json
+.idea
+.DS_Store
+*.suo
+*.ntvs*
+*.njsproj
+*.sln
+*.sw?
diff --git a/apps/compliance-portal/README.md b/apps/compliance-portal/README.md
new file mode 100644
index 000000000..53e64ffe9
--- /dev/null
+++ b/apps/compliance-portal/README.md
@@ -0,0 +1 @@
+# Compliance Portal app
diff --git a/apps/compliance-portal/eslint.config.mjs b/apps/compliance-portal/eslint.config.mjs
new file mode 100644
index 000000000..a33dd3ff0
--- /dev/null
+++ b/apps/compliance-portal/eslint.config.mjs
@@ -0,0 +1,12 @@
+import { configs } from "@probo/eslint-config";
+import { defineConfig } from "eslint/config";
+
+export default defineConfig([
+ configs.base,
+ configs.ts,
+ configs.imports,
+ configs.react,
+ configs.relay,
+ configs.stylistic,
+ configs.languageOptions.browser,
+]);
diff --git a/apps/compliance-portal/graphql.config.yml b/apps/compliance-portal/graphql.config.yml
new file mode 100644
index 000000000..2e608af40
--- /dev/null
+++ b/apps/compliance-portal/graphql.config.yml
@@ -0,0 +1,5 @@
+schema: '../../pkg/server/api/trust/v1/schema.graphql'
+extensions:
+ endpoints:
+ CompliancePage:
+ url: http://localhost:8080/api/trust/v1/graphql
diff --git a/apps/compliance-portal/index.html b/apps/compliance-portal/index.html
new file mode 100644
index 000000000..e92a7a4f2
--- /dev/null
+++ b/apps/compliance-portal/index.html
@@ -0,0 +1,39 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ {{.Title}}
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/apps/compliance-portal/package.json b/apps/compliance-portal/package.json
new file mode 100644
index 000000000..a46c0284f
--- /dev/null
+++ b/apps/compliance-portal/package.json
@@ -0,0 +1,42 @@
+{
+ "name": "@probo/compliance-portal",
+ "private": true,
+ "version": "0.0.0",
+ "type": "module",
+ "scripts": {
+ "dev": "vite --port 5175",
+ "build": "tsc -b && vite build",
+ "lint": "eslint . --concurrency 2",
+ "check": "tsc --noEmit -p tsconfig.app.json",
+ "preview": "vite preview"
+ },
+ "dependencies": {
+ "@probo/ui": "1.0.0",
+ "clsx": "^2.1.1",
+ "react": "^19.2.7",
+ "react-dom": "^19.2.7",
+ "react-relay": "^21.0.1",
+ "react-router": "^8.0.0",
+ "relay-runtime": "^21.0.1"
+ },
+ "devDependencies": {
+ "@probo/eslint-config": "1.0.0",
+ "@probo/eslint-plugin-relay-types": "^1.0.0",
+ "@tailwindcss/vite": "^4.3.1",
+ "@types/node": "^25.9.3",
+ "@types/react": "^19.2.17",
+ "@types/react-dom": "^19.2.3",
+ "@types/react-relay": "^18.2.1",
+ "@types/relay-runtime": "^20.1.1",
+ "@vitejs/plugin-react": "^6.0.2",
+ "babel-plugin-relay": "^21.0.1",
+ "eslint": "^10.5.0",
+ "graphql": "^17.0.1",
+ "tailwindcss": "^4.3.1",
+ "typescript": "~6.0.3",
+ "vite": "^8.0.16"
+ },
+ "volta": {
+ "node": "24.4.0"
+ }
+}
diff --git a/apps/compliance-portal/tsconfig.app.json b/apps/compliance-portal/tsconfig.app.json
new file mode 100644
index 000000000..1fdb3f133
--- /dev/null
+++ b/apps/compliance-portal/tsconfig.app.json
@@ -0,0 +1,31 @@
+{
+ "compilerOptions": {
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.app.tsbuildinfo",
+ "target": "ES2020",
+ "useDefineForClassFields": true,
+ "lib": ["ES2022", "DOM", "DOM.Iterable"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": false,
+ "verbatimModuleSyntax": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+ "jsx": "react-jsx",
+ "baseUrl": ".",
+ "paths": {
+ "#/*": ["src/*"]
+ },
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "erasableSyntaxOnly": true,
+ "noFallthroughCasesInSwitch": true,
+ "noUncheckedSideEffectImports": true
+ },
+ "include": ["src"]
+}
diff --git a/apps/compliance-portal/tsconfig.json b/apps/compliance-portal/tsconfig.json
new file mode 100644
index 000000000..1ffef600d
--- /dev/null
+++ b/apps/compliance-portal/tsconfig.json
@@ -0,0 +1,7 @@
+{
+ "files": [],
+ "references": [
+ { "path": "./tsconfig.app.json" },
+ { "path": "./tsconfig.node.json" }
+ ]
+}
diff --git a/apps/compliance-portal/tsconfig.node.json b/apps/compliance-portal/tsconfig.node.json
new file mode 100644
index 000000000..537e6f3e1
--- /dev/null
+++ b/apps/compliance-portal/tsconfig.node.json
@@ -0,0 +1,27 @@
+{
+ "compilerOptions": {
+ "tsBuildInfoFile": "./node_modules/.tmp/tsconfig.node.tsbuildinfo",
+ "allowJs": true,
+ "target": "ES2022",
+ "lib": ["ES2023"],
+ "module": "ESNext",
+ "skipLibCheck": true,
+
+ /* Bundler mode */
+ "moduleResolution": "bundler",
+ "allowImportingTsExtensions": false,
+ "verbatimModuleSyntax": true,
+ "moduleDetection": "force",
+ "noEmit": true,
+
+ /* Linting */
+ "strict": true,
+ "noUnusedLocals": true,
+ "noUnusedParameters": true,
+ "erasableSyntaxOnly": true,
+ "noFallthroughCasesInSwitch": true,
+ "noUncheckedSideEffectImports": true,
+ "types": ["@probo/eslint-plugin-relay-types"]
+ },
+ "include": ["vite.config.ts", "eslint.config.mjs"]
+}
diff --git a/apps/compliance-portal/vite.config.ts b/apps/compliance-portal/vite.config.ts
new file mode 100644
index 000000000..383551be7
--- /dev/null
+++ b/apps/compliance-portal/vite.config.ts
@@ -0,0 +1,42 @@
+// Copyright (c) 2025-2026 Probo Inc .
+//
+// Permission to use, copy, modify, and/or distribute this software for any
+// purpose with or without fee is hereby granted, provided that the above
+// copyright notice and this permission notice appear in all copies.
+//
+// THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES WITH
+// REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF MERCHANTABILITY
+// AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY SPECIAL, DIRECT,
+// INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES WHATSOEVER RESULTING FROM
+// LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION OF CONTRACT, NEGLIGENCE OR
+// OTHER TORTIOUS ACTION, ARISING OUT OF OR IN CONNECTION WITH THE USE OR
+// PERFORMANCE OF THIS SOFTWARE.
+
+import { fileURLToPath, URL } from "node:url";
+
+import tailwindcss from "@tailwindcss/vite";
+import react from "@vitejs/plugin-react";
+import { defineConfig } from "vite";
+
+// https://vite.dev/config/
+export default defineConfig({
+ plugins: [react({ babel: { plugins: ["relay"] } }), tailwindcss()],
+ build: {
+ assetsDir: "assets",
+ },
+ base: "./",
+ server: {
+ port: 5175,
+ proxy: {
+ "^/trust/[^/]+/api": {
+ target: "http://localhost:8080",
+ changeOrigin: true,
+ },
+ },
+ },
+ resolve: {
+ alias: {
+ "#": fileURLToPath(new URL("./src", import.meta.url)),
+ },
+ },
+});
diff --git a/relay.config.json b/relay.config.json
index 9167b07ba..999d0d535 100644
--- a/relay.config.json
+++ b/relay.config.json
@@ -6,7 +6,8 @@
"sources": {
"apps/console/src/pages/iam": "iam",
"apps/console/src": "core",
- "apps/trust/src": "trust"
+ "apps/trust/src": "trust",
+ "apps/compliance-portal/src": "complianceportal"
},
"projects": {
"core": {
@@ -49,6 +50,16 @@
"CursorKey": "string",
"EmailAddr": "string"
}
+ },
+ "complianceportal": {
+ "schema": "pkg/server/api/trust/v1/schema.graphql",
+ "language": "typescript",
+ "noFutureProofEnums": true,
+ "customScalarTypes": {
+ "Datetime": "string",
+ "CursorKey": "string",
+ "EmailAddr": "string"
+ }
}
}
}