Appearance
Admin Setup
This guide walks you through setting up BluePLM for your organization. Follow the steps in order.
Prerequisites
You need:
- A Supabase account (free tier works)
- BluePLM installed on your computer
- (Optional) A Google Cloud account for Google Sign-In
- (Recommended) An email provider account (Resend or SendGrid) for reliable invite emails
Step 1: Create a Supabase Project
- Go to supabase.com and sign in or create an account
- Click New Project
- Choose a project name and set a strong database password
- Select a region close to your team
- Click Create new project and wait ~2 minutes for provisioning
Once ready, go to Settings → API and note:
- Project URL (e.g.,
https://abcdefgh.supabase.co) - anon/public key (starts with
eyJ...)
You'll enter these in BluePLM later.
Increase Max Rows (Important for Large Vaults)
While in the API settings, increase the maximum rows returned per query:
- In Settings → API, look at the left sidebar and click Data API
- Find Max Rows (default is 1,000)
- Increase this to a value well beyond your expected maximum vault size (e.g.,
1000000for 1 million rows) - Click Save
Plan for Growth
If your vault exceeds the max rows setting, queries may return incomplete results. Set this higher than you think you'll need — there's no performance penalty for a higher limit.
Step 2: Set Up Google OAuth (Recommended)
Google Sign-In provides the smoothest authentication experience. Skip this step if you prefer email/password only.
In Google Cloud Console
- Go to Google Cloud Console
- Create a new project or select an existing one
- Navigate to OAuth consent screen
- Choose External (recommended) — allows any Google account to sign in
- Choose Internal only if you want to restrict sign-in to your Google Workspace domain exclusively
- Fill in:
- App name: "BluePLM"
- User support email: your email
- Developer contact: your email
- Click Save and Continue through the scopes (defaults are fine)
- Go to Credentials → Create Credentials → OAuth 2.0 Client ID
- Select Web application
- Add this Authorized redirect URI:Replace
https://YOUR-PROJECT-REF.supabase.co/auth/v1/callbackYOUR-PROJECT-REFwith your Supabase project reference (the subdomain from your Project URL). - Click Create and copy your Client ID and Client Secret
In Supabase Dashboard
- Go to Authentication → Providers → Google
- Toggle Enable Sign in with Google
- Paste your Client ID and Client Secret
- Click Save
- Go to Authentication → URL Configuration
- Set Site URL to:
http://localhost - Add these Redirect URLs:
http://localhosthttp://localhost:5173http://127.0.0.1
Step 3: Create Storage Bucket
Do This Before Step 4
BluePLM stores file content in this bucket. Create it before BluePLM creates the schema in Step 4.
- Go to Storage in Supabase Dashboard
- Click New Bucket
- Name it exactly:
vault - Uncheck "Public bucket" (must be private)
- Click Create bucket
The schema (module 10-source-files.sql) installs the bucket's access policies and removes any other policy that names the vault bucket. File content is readable only by members who can see a file or version that uses it (vault access), by whoever uploaded it, and by organization admins.
Step 4: Connect BluePLM and Create the Schema
BluePLM creates the database schema itself (tables, functions, Row Level Security and storage policies), and applies every later schema update the same way. There is no SQL to paste.
- Download and open BluePLM (the desktop app; BluePLM Web cannot create a schema)
- Complete the language/analytics setup if this is your first launch
- On the Setup screen, click "I'm setting up BluePLM for my organization"
- Enter:
- Supabase URL:
https://xxxxx.supabase.co - Anon Key: starts with
eyJ... - Organization Slug (optional): e.g.,
your-company
- Supabase URL:
- Click Connect to Supabase, then sign in
- BluePLM shows Set up the BluePLM database. Paste the database connection string: in the Supabase Dashboard, Connect > Session pooler (port 5432), with your database password filled in
- Click Check database to see what will be installed, then Apply upgrade. BluePLM creates the schema, verifies it, and records what it applied
Remember on this computer
Tick Remember on this computer to let BluePLM apply future schema updates automatically when you open a new version. The connection string is encrypted with the operating system's key store and never leaves this computer. Without it, BluePLM asks for the string again when an update needs one.
The connection string is a database password
Anyone with it can change your database. Never share it with team members; they only need the Organization Code (Step 6).
Step 5: Create Your Organization
This needs the schema from Step 4 at version 502 or later. Run this in the Supabase SQL Editor (customize the values):
sql
SELECT org_create_with_founder(
'Your Company Name', -- display name
'your-company', -- URL-safe slug: lower case, digits, hyphens
'[email protected]', -- the address you signed in with in Step 4 (any provider, gmail.com too)
ARRAY['yourcompany.com'] -- your team's email domains (optional; public mail domains are refused)
);One call does all of it:
- creates the organization, with its default teams (Administrators, New Users) and job titles
- sets its email domains: anyone who signs in with an address at one of them joins the New Users team
- invites you as the organization's administrator, in the Administrators team
The invitation is why your own address can be a personal one: it names you, and a domain names everyone at it.
Then turn on the sign-up hook, so only people who belong to your organization can create an account:
- In your Supabase Dashboard, go to Authentication → Hooks
- Add a Before User Created hook of type Postgres
- Schema
public, functionauth_hook_before_user_created - Save
Until the organization exists the hook refuses everyone with "this BluePLM database has no organization yet", so do Step 5 first. See Only Invited People Can Sign Up for what it admits.
Step 6: Copy the Organization Code
- In BluePLM, copy the generated Organization Code (save this for team members!)
Keep the Code Secure
The Organization Code contains your Supabase anon key encoded. Share it only with trusted team members.
Using BluePLM in a browser (blueplm.io)
Your team can also use BluePLM at blueplm.io with the same Organization Code: on the sign-in page choose Change organization and paste the code. Before that:
- In Supabase, go to Authentication > URL Configuration > Redirect URLs and add
https://blueplm.ioandhttps://blueplm.io/**. Without them, Google sign-in cannot return to the browser app. Your Google OAuth client needs no change. - The browser app reaches hosted Supabase projects (
*.supabase.co) only. A self-hosted Supabase works in the desktop app but not at blueplm.io. - Checking files in and out and everything that touches SOLIDWORKS stays in the desktop app.
Optimize Performance (Windows)
On Windows, antivirus software (especially Windows Defender) can significantly slow down file operations by scanning files every time they're opened for writing. For CAD files like SolidWorks parts and assemblies, this can add 10-15 seconds to operations that should take 1-2 seconds.
We strongly recommend adding your vault folder to Windows Defender exclusions.
Add Exclusion via Windows Security
- Open Settings (Win + I)
- Go to Privacy & Security → Windows Security
- Click Virus & threat protection
- Under "Virus & threat protection settings", click Manage settings
- Scroll to Exclusions and click Add or remove exclusions
- Click Add an exclusion → Folder
- Navigate to your vault folder (e.g.,
C:\BluePLM\vault-name) and select it
Add Exclusion via PowerShell (Admin)
Run PowerShell as Administrator and execute:
powershell
Add-MpPreference -ExclusionPath "C:\BluePLM"To verify the exclusion was added:
powershell
Get-MpPreference | Select-Object -ExpandProperty ExclusionPathThird-Party Antivirus
If you use antivirus software other than Windows Defender (Norton, McAfee, Bitdefender, etc.), you'll need to add the exclusion in that software's settings instead.
Security Consideration
Excluding folders from antivirus scanning reduces protection for those files. Only exclude trusted vault folders that contain your organization's CAD files.
Step 7: Sign In Again
Sign out of BluePLM and sign in again with the address you gave in Step 5. Your invitation is applied at that sign-in: you become a member of the organization, with the admin role, in the Administrators team. There is no SQL to run.
If BluePLM still shows no organization, you signed in with a different address than the one in Step 5. Sign in with that one, or invite the address you use as an administrator too:
sql
INSERT INTO pending_org_member (org_id, email, role, team_ids, notes)
SELECT o.id, lower('[email protected]'), 'admin', ARRAY[t.id], 'Founding administrator'
FROM organization o JOIN team t ON t.org_id = o.id AND t.name = 'Administrators'
WHERE o.slug = 'your-company';Step 8: Create Your First Vault
Vaults are containers for files. Create at least one to start working.
First, get your organization ID:
sql
SELECT id FROM organization WHERE slug = 'your-company';Then create the vault (replace the UUID):
sql
INSERT INTO vault (org_id, name, slug, storage_bucket, is_default)
VALUES (
'ORG-UUID-HERE', -- Your organization ID from above
'Main Vault', -- Display name
'main-vault', -- URL-safe slug
'vault', -- Storage bucket name (must match step 3)
true -- Make this the default vault
);Step 9: Create Default Workflow
Files need a workflow to track their lifecycle states (WIP → In Review → Released → Obsolete).
Create it in BluePLM, signed in as the admin from Step 7: open Workflows and create a new workflow (Create new workflow). The database function behind it, workflow_create_default(), checks that the caller is an organization admin, so it cannot be run from the SQL Editor.
This creates the standard release workflow with:
- WIP (Work In Progress) - Initial state
- In Review - Ready for approval
- Released - Approved for use
- Obsolete - Deprecated/retired
Step 10: Deploy REST API (Required for Invites)
The REST API server is needed for sending invite emails and ERP integrations.
Deploy to Railway (Recommended)
- Go to railway.app/new
- Select "Deploy from Docker Image"
- Enter:
ghcr.io/bluerobotics/blueplm-api:latest - Add these environment variables (from Supabase Dashboard → Settings → API):
| Variable | Value |
|---|---|
SUPABASE_URL | Your Project URL |
SUPABASE_KEY | anon/public key |
SUPABASE_SERVICE_KEY | service_role key ⚠️ |
- Deploy and copy your API URL (e.g.,
https://your-app.railway.app)
Keep service_role Key Secret
The SUPABASE_SERVICE_KEY bypasses Row Level Security. Never expose it in client-side code.
That is the whole list
There is nothing else you have to set to get a safely configured API. The image bakes in no behaviour switches, and every default is the conservative one: a 500 returns only an error id and never the server's stack trace, and BluePLM itself is always allowed through CORS whatever else you configure.
Earlier versions behaved differently. NODE_ENV defaulted to development, and because neither Railway nor Render sets it for a prebuilt image, an API deployed by following these steps returned full stack traces to anyone who asked. If you deployed before BluePLM 4.0.0, pull the current image — ghcr.io/bluerobotics/blueplm-api:latest, then redeploy. You do not need to add a variable to fix it, and you should not add NODE_ENV=development.
Optional Variables
Set these in the same place as the three above — the platform's own environment settings — so that changing your mind later is a variable edit and a restart.
| Variable | Default | What it does |
|---|---|---|
ENABLE_DOCS | true | Serves browsable API documentation at <your-api-url>/docs. Set to false to keep your API's shape off the public internet. It affects nothing but the documentation page. |
CORS_ORIGINS | (empty) | Extra browser origins allowed to call the API, comma-separated. You almost certainly do not need this: Odoo, scripts and other server-to-server callers are not subject to CORS, and BluePLM is always allowed. |
TRUST_PROXY | loopback,linklocal,uniquelocal,100.64.0.0/10 | The reverse proxies trusted for the caller's address, as a comma-separated list of addresses, CIDR ranges or the names loopback, linklocal, uniquelocal; off trusts none. The default suits Render; Railway's edge connects from a public address, so on Railway the client address comes from CLIENT_IP_HEADER instead. It replaces API 3.x's TRUST_PROXY_HOPS, which is no longer read. |
CLIENT_IP_HEADER | x-real-ip on Railway, unset elsewhere | A header the hosting edge overwrites with the caller's address on every request, used for the per-client rate limit and the request log (first entry, and only when it is an IP; otherwise the TRUST_PROXY address). Railway is detected by RAILWAY_ENVIRONMENT_NAME or RAILWAY_PROJECT_ID. Set it only to a header your edge always overwrites, since a caller can send any header; off turns it off. |
NODE_ENV | production | Leave it alone unless you are developing BluePLM itself. |
Configure in BluePLM
- Go to Settings → Integrations → REST API
- Enable "Use External API"
- Enter your Railway API URL
- Click Test Connection to verify
Alternative Deployment Options
See the API README for:
- Render deployment
- Fly.io deployment
- Self-hosted Docker
Step 11: Configure Email Delivery (Recommended)
By default, Supabase uses their shared email domain ([email protected]) which often lands in spam. Configure a custom SMTP provider for reliable email delivery.
Option A: Resend (Recommended)
Resend offers 100 free emails/day and easy setup.
1. Set Up Resend
- Sign up at resend.com
- Go to Domains → Add Domain
- Enter your domain (e.g.,
blueplm.iooryourcompany.com) - Add the DNS records Resend provides to your domain registrar
- Wait for verification (~5 minutes)
- Go to API Keys → Create API Key and copy it
2. Configure in Supabase
- Go to Project Settings → Authentication
- Scroll to SMTP Settings → Toggle Enable Custom SMTP
- Fill in:
| Field | Value |
|---|---|
| Host | smtp.resend.com |
| Port | 465 |
| Username | resend |
| Password | Your API key (e.g., re_xxxxxxxxx...) |
| Sender email | [email protected] |
| Sender name | BluePLM |
- Click Save
Option B: SendGrid
SendGrid also offers a free tier (100 emails/day).
- Sign up and verify your domain
- Create an API key with Mail Send permissions
- Use these SMTP settings:
| Field | Value |
|---|---|
| Host | smtp.sendgrid.net |
| Port | 465 |
| Username | apikey |
| Password | Your API key |
| Sender email | [email protected] |
| Sender name | BluePLM |
Test Your Configuration
After setup, invite yourself (using a different email) to verify emails arrive in the inbox, not spam.
Step 12: Set Up Email Templates (Required for Invites)
BluePLM includes branded email templates for authentication emails. The invite template is required — it displays the Organization Code directly in the email so invited users can copy/paste it into BluePLM.
Required for User Invites
Without the invite template, users won't see their Organization Code in the invite email. Set this up before inviting team members.
Set Up the Invite Template
- Go to Authentication → Email Templates in Supabase Dashboard
- Select Invite user
- Set Subject to:
You've been invited to BluePLM - Copy the HTML from
supabase/email-templates/invite-user.html - Paste into the Body (HTML) field
- Click Save
The invite email will now show:
- Organization name
- Organization Code (copyable) — users paste this into BluePLM
- Download instructions
- Link to blueplm.io/downloads
Other Templates (Optional)
For consistent branding, you can also update these templates from supabase/email-templates/:
| Template | Subject Line |
|---|---|
| Confirm sign up | Confirm your BluePLM account |
| Magic link | Your BluePLM sign-in link |
| Change email | Confirm your new email address |
| Reset password | Reset your BluePLM password |
Sharing with Team Members
There are two ways to add team members:
Option A: Send Invites (Recommended)
Use BluePLM's invite feature in Settings → Members & Teams:
- Click Invite User
- Enter their email address
- They receive an email with:
- The Organization Code (ready to copy)
- Link to download BluePLM
- Setup instructions
This is the easiest method — users get everything they need in one email.
Option B: Share Code Manually
Share the Organization Code generated in Step 6 directly:
- Go to Settings → Members & Teams
- Click Show Organization Code
- Send the code to team members along with download link
Team members then:
- Download BluePLM from blueplm.io/downloads
- Select "I have an Organization Code"
- Paste the code
- Sign in with Google/email/phone
The code contains your Supabase connection info encoded — team members don't need to enter URLs or keys manually.
See User Setup Guide for detailed team member instructions.
Upgrading the Database
BluePLM upgrades the database itself. When a new version needs a newer schema, an org admin opening the desktop app sees Database upgrade required; everyone else sees Database upgrade needed and waits. The admin pastes the database connection string (as in Step 4), clicks Check database to see what will run, then Apply upgrade. With Remember on this computer ticked, the upgrade runs on its own the next time that admin starts the new version.
Upgrading from 4.x to 5.0 works the same way. BluePLM brings a database older than 4.10 up to 4.10 first, then applies the 5.0 upgrade (supabase/migrations/0500_from_4x.sql), which renames every table and function to its 5.0 name. After 5.0, each schema change is a numbered migration in supabase/migrations/, applied in order. Each step runs in its own transaction: a failing step is rolled back, and the steps before it stay applied.
Everyone moves to 5.0
A 4.x app cannot use a 5.0 database, and a 5.0 app below the organization's minimum version (client_min_version()) shows Update required and installs the update on its own. Have everyone check in their work before you upgrade.
Extensions with their own SQL
The 5.0 upgrade removes every access policy, including an extension's, because policies call core functions by name. An extension that ships SQL (such as the private extension blueplm.customers) must have its 5.0 SQL applied after the upgrade, in the Supabase SQL Editor.
Only Invited People Can Sign Up (Recommended)
From schema 502, BluePLM ships a Supabase Auth hook that refuses to create an account for an address that belongs nowhere. An account is created only for:
- an open invitation (Members & Teams → Invite, or Step 5 for the founding admin),
- an address at one of your organization's email domains (set in Members & Teams; public mail providers such as gmail.com cannot be added),
- a supplier contact,
Anyone else sees "You haven't been invited to an organization. Ask your administrator for an invite." Without the hook, they get an account with no organization and can see nothing.
It is turned on in Step 5. On a database that was set up before schema 502, turn it on the same way once the database is on 502 (Authentication → Hooks → Before User Created, Postgres, public.auth_hook_before_user_created). Through the Management API: hook_before_user_created_enabled = true, hook_before_user_created_uri = pg-functions://postgres/public/auth_hook_before_user_created.
Invite people before they sign in. An invitation sent after someone was refused works; they sign in again.
Security Monitoring
From schema 502, the database checks itself every 10 minutes and notifies your administrators in BluePLM's notifications: new administrators, members who joined through an email domain, mass file or storage deletes, bursts of password-reset requests, accounts left without an organization, failed or overdue server backups, and schema drift. Thresholds are in Settings → Security Monitoring. It runs in your own database through pg_cron (enabled on Supabase by default). If your Postgres has no pg_cron, schedule SELECT public.security_monitor_run(); every 10 minutes yourself. Nothing is sent outside your database.
Troubleshooting
Uploads fail with "Bucket not found"
Create the vault storage bucket (Step 3). Its name must be exactly vault.
Google Sign-In shows "Access blocked: org_internal"
Your Google OAuth app is set to "Internal". Go to Google Cloud Console → APIs & Services → OAuth consent screen and change the user type to External. This allows any Google account to sign in, not just your Google Workspace users.
Google Sign-In shows "redirect_uri_mismatch"
Verify your Supabase project URL is in Google Cloud's authorized redirect URIs exactly:
https://YOUR-PROJECT-REF.supabase.co/auth/v1/callbackUsers can't see any vaults
Grant vault access via Settings → Members & Teams. Non-admin users don't see vaults automatically.
Organization Code doesn't work
Regenerate the code by disconnecting and reconnecting to Supabase in BluePLM.
"You haven't been invited to an organization"
The sign-up hook found no invitation, organization email domain or supplier contact for that address. Invite the person (Members & Teams), or add their company domain to the organization. The founding admin signs in with the exact address given in Step 5.
"This BluePLM database has no organization yet"
The sign-up hook is on but Step 5 has not run. Run it, then sign in again.
Invite emails going to spam
Configure custom SMTP (Step 11). Supabase's default email domain ([email protected]) is often flagged as spam.
"Service key not configured" error when inviting users
- Verify
SUPABASE_SERVICE_KEYis set in your Railway environment variables - Redeploy the API service after adding the variable (Railway doesn't auto-restart)