Dokumentation
open-crm
Fullständig manual för Desktop CRM, Remote, Kundportal, Signering och Formulärapp.
Vad är open-crm?
open-crm är ett fullständigt CRM-system byggt för tjänsteföretag — bygg, hantverk, konsulter och liknande verksamheter. Det distribueras som öppen källkod under MIT-licens och körs självhostat: du äger all data, ingen månadsavgift, ingen inlåsning.
Systemet täcker hela affärsflödet i en enda sammanhängande miljö: kundregistrering, projektplanering, tidplan, offertskrivning med ROT-avdrag, digital signering, kostnadsuppföljning, orderhantering, fakturering, intern kommunikation och automatiserade AI-arbetsflöden.
Kärnan är en Electron-app (Desktop CRM) som kör lokalt på kontorets datorer och synkroniseras mot en Supabase-databas. Runt den finns tre kompletterande webbappar — Remote för fältpersonal, Kundportal för klienter och Signering för digital offertgodkännande.
De sex apparna
open-crm-ekosystemet består av sex separata applikationer som delar samma databas:
Desktop CRM
Desktop CRMElectron-app för Windows, macOS och Linux. Huvudverktygen för administratörer och projektledare. Hanterar allt från kunder och offerter till ekonomi och kommunikation.
Remote
RemoteMobiloptimerad webb-app för fältpersonal. Tillgång till kalender, internchatt, tidrapportering och kundöversikt. Designad för att fungera på en telefon med ena handen.
Anställdapp
AnställdappWebb-app för fältanställda. Schema, uppgifter och chatt optimerat för telefon. Stöder svenska, engelska, spanska och polska.
Kundportal
KundportalWebb-app för dina kunder. Klienten loggar in och ser sina projekt, offerter och kan kommunicera direkt med företaget. Mobile-first.
Signering
SigneringPortal för digital signering av offerter. Kunden behöver inte logga in — offerten levereras via en unik länk och signeras med ett klick.
Formulärapp
FormulärappWebbapp för klientfrågeformulär. Generera formulär med AI, skicka länken till kunden och samla in svar som används direkt av AI-offertflödet.
Systemkrav
Desktop CRM
- Node.js 20 LTS eller senare
- npm 10 eller senare
- Git
- macOS 12+, Windows 10+ eller Linux (Debian/Ubuntu rekommenderas)
- Minimum 4 GB RAM, 2 GB ledigt diskutrymme
Webbapparna (Remote / Kundportal / Signering)
Alla tre webbappar är Next.js-projekt och kan hostarnas på valfri plattform som stöder Node.js — Vercel, Railway, en egen VPS eller liknande. De kräver Node.js 20+ och delar Supabase-databasen med Desktop CRM.
Databas
open-crm använder Supabase (hanterad PostgreSQL) som databas. Supabase Cloud med gratis tier räcker för de flesta installationer. Självhostad Supabase stöds också — se supabase.com/docs/guides/self-hosting för instruktioner.
Installation & setup
Desktop CRMKlona repot och installera beroenden:
git clone https://github.com/rankgnar/open-crm
cd open-crm
npm installSkapa .env-fil
Skapa filen .env i projektets rot. Alla fyra variabler krävs:
SUPABASE_URL=https://<ditt-projekt-ref>.supabase.co
SUPABASE_ANON_KEY=<din-anon-nyckel>
SUPABASE_SERVICE_KEY=<din-service-nyckel>
SUPABASE_ACCESS_TOKEN=<din-personal-access-token>Var du hittar nycklarna:
- SUPABASE_URL och ANON_KEY: supabase.com → ditt projekt → Settings → API → Project URL / anon key
- SUPABASE_SERVICE_KEY: samma sida → service_role key (håll hemlig, används bara server-side)
- SUPABASE_ACCESS_TOKEN: supabase.com/dashboard/account/tokens → "Generate new token"
Starta appen
npm run devElectron-fönstret öppnas automatiskt med hot-reload. Vid första start körs databasmigreringar automatiskt — tabeller skapas i din Supabase-instans utan manuella steg.
_applied_migrations. Varje fil i supabase/migrations/ körs exakt en gång, i lexikografisk ordning. Det är idempotent — det är säkert att starta om appen.Bygg för produktion
npm run build
# Output: /dist/<platform>/Bygg genererar en installationsfil per plattform — .dmg för macOS, .exe för Windows och .AppImage / .deb för Linux.
Workspace
Desktop CRMWorkspace är startskärmen i appen. Den samlar verksamhetens viktigaste nyckeltal i en enda vy utan att du behöver navigera runt i systemet.

Workspace visar i realtid:
Kunder & Projekt
Aktiva kunder, öppna projekt och pipelinestatus
Förslag
Offerter under behandling, signerade och väntande
Order
Pågående ordrar med statusöversikt
Ekonomi
Kostnader, fakturaflöde och budgetstatus
Personal
Tillgänglighet och aktivitetsstatus för teamet
AI-status
Senaste AI-arbetsflöden och pågående körningar
Workspace aggregerar data från alla moduler — den har inga egna tabeller i databasen.
Kunder
Desktop CRMKundregistret är grunden i systemet. Varje kund har kontaktuppgifter, anteckningar och en komplett historik av projekt, offerter och kommunikation.

Fält per kund
- Namn, organisationsnummer (valfritt)
- Primär kontaktperson: namn, e-post, telefon
- Faktureringsadress
- Anteckningar (fritext)
- Status: Aktiv / Inaktiv
Åtgärder
- Skapa ny kund — fyll i formuläret via "Ny kund"-knappen
- Redigera kontaktuppgifter direkt i detaljvyn
- Se alla projekt, offerter och fakturor kopplade till kunden
- Bjud in kunden till Kundportalen (se Kundportal-sektionen)
Tabell: kunder · IPC: db:kunder:list, db:kunder:create, db:kunder:update
Projekt
Desktop CRMProjekt är navet i systemet. Nästan alla moduler — kalender, tidplan, förslag, order, kostnader, fakturor — är kopplade till ett specifikt projekt. En kund kan ha hur många projekt som helst.

Projektstatus
Planerad
Projektet är skapat men arbetet har inte börjat
Pågående
Aktivt projekt med löpande uppföljning
Slutförd
Avslutat projekt, arkiveras men raderas ej
Avbruten
Projekt som ej genomförs
Pausad
Tillfälligt stoppad, återupptas senare
Fält per projekt
- Titel och beskrivning
- Kopplad kund
- Status och startdatum / beräknat slutdatum
- Budgetbelopp (SEK inkl. moms)
- Intern anteckning
Tabell: projekt · IPC: db:projekt:list, db:projekt:get, db:projekt:create, db:projekt:update
Kalender & Tidplan
Desktop CRMKalendermodulen är en veckokalender för planering av händelser kopplade till projekt och personal. Tidplanen ger en visuell Gantt-liknande vy per projekt.

Händelsetyper i Kalender
Uppgift
Intern arbetsuppgift att slutföra
Besök
Kundmöte eller platsbesök
Leverans
Materialleverans till arbetsplats
Möte
Internt eller externt möte
Carry-over — ej slutförda händelser
Händelser som passerat datum och inte markerats som slutförda (och inte är återkommande) visas automatiskt i nuvarande vecka. Historiken är oföränderlig — händelserna visas i dag men ändrar inte ursprungsdatum.

Tidplan
Tidplanen visar ett projekts faser och milstolpar i en horisontell tidslinje. Varje fas kan ha ett start- och slutdatum och kopplas till Kalenders händelser. Tidplan är per projekt — välj projekt i dropdown för att se dess plan.
Tabeller: kalender_events, tidplan_faser · IPC: db:kalender:list, db:tidplan:list
Förslag & Offert
Desktop CRMFörslag (offert) konsoliderar projektets arbets- och materialkostnader i ett strukturerat dokument som kan skickas till kunden för godkännande och digital signering.

Struktur
Ett förslag byggs upp av faser — t.ex. "Rivning", "Stomme", "Ytskikt". Varje fas innehåller rad-för-rad specificerade arbets- och materialkostnader. Systemet beräknar automatiskt delsummor, moms och ROT-avdrag.
ROT-avdrag
Swedish ROT-avdrag (30 % skatteåterbäring för hushållsarbeten) hanteras per rad. Markera vilka rader som kvalificerar — totalen justeras automatiskt och visas separat i PDF-offerten.
AI-genererade offerter
Via AI Workflows-modulen kan du automatisera offertskrivning baserat på projektbeskrivning och historik. Systemet genererar ett utkast som du sedan justerar manuellt.
Förslagens status
- Utkast — redigeras och förfinas internt
- Skickad — offerten har levererats till kunden
- Signerad — kunden har signerat digitalt
- Avvisad — kunden har avböjt
Tabell: forslag, forslag_faser, forslag_rader · IPC: db:forslag:list, db:forslag:create
Skicka för signering
Desktop CRMFlödet för att skicka en offert för digital signering sker helt inifrån Desktop CRM. Kunden behöver inte ha ett konto i Kundportalen.
Steg-för-steg
- 1
Öppna förslaget
Gå till Förslag och öppna det aktuella förslaget.
- 2
Skicka för signering
Klicka "Skicka för signering". Systemet genererar en unik URL och skickar ett e-postmeddelande till kundens e-postadress med en länk.
- 3
Kunden signerar
Kunden öppnar länken i Signeringsportalen, granskar offerten och klickar "Signera". Ingen inloggning krävs.
- 4
Arkivering
Signaturen stämplas med tidsstämpel, IP-adress och kryptografisk hash. PDF-dokumentet arkiveras och skickas automatiskt till båda parter.
- 5
Status uppdateras
Förslaget markeras automatiskt som "Signerat" i Desktop CRM.
Order & ÄTA
Desktop CRMOrdermodulen hanterar beställningar av material och tjänster kopplade till projekt. ÄTA-modulen (ändrings- och tilläggsarbeten) dokumenterar arbeten som tillkommer utanför ursprungsofferten.

Orderstatus
- Utkast — skapas och redigeras internt
- Godkänd — internt godkänd för beställning
- Skickad — beställning skickad till leverantör
- Levererad — material/tjänst mottagen
- Avbruten — order ej genomförd

ÄTA — Ändrings- och tilläggsarbeten
ÄTA-poster skapas när kunden beställer arbeten utanför den ursprungliga offerten. Varje ÄTA kopplas till ett projekt och innehåller beskrivning, timmar/material och pris. ÄTA-poster kan faktureras separat eller samlas till en slutfaktura.
Tabeller: order, ata · IPC: db:order:list, db:ata:list
Ekonomi
Desktop CRMEkonomimodulerna ger fullständig kontroll över kostnader, fakturering och kvitton per projekt.
Kostnader

Kostnadsmodulen separerar arbets- och materialkostnader. Varje post kopplas till ett projekt och eventuellt till en fas i Tidplanen.
- Arbetskostnad: antal timmar × timpris per resurs
- Materialkostnad: antal × enhetspris per artikel
- ROT-markering per post
- Automatisk summering mot projektets budget
Tabeller: arbetskostnad, materialkostnad
Fakturering

Fakturamodulen hanterar utgående fakturor. Fakturor kopplas till projekt och kan innehålla rader från kostnader, ÄTA eller manuellt tillagda poster.
- Status: Planerad → Skickad → Betald / Förfallen
- Förfallodatum med automatisk påminnelseflagga
Tabell: fakturor · IPC: db:fakturor:list
Kvitto

Kvittomodulen tar emot inkommande kvitton (inköp, utlägg) och kopplar dem till projekt och kostnadsrader. Kvitton kan importeras som bild och matchas mot befintliga materialkostnadsposter.
E-post & Chat
Desktop CRME-post

Den inbyggda e-postmodulen är en fullständig inkorg integrerad via Zoho Mail. Meddelanden kopplas automatiskt till rätt kund och projekt baserat på avsändarens e-postadress.
- Läs, svara och skicka e-post direkt i appen
- Automatisk kundkoppling baserat på avsändar-epost
- Anpassningsbara mallar för offerter, fakturabekräftelser och uppföljningar
- SMTP-stöd för alternativa e-postleverantörer
Chat

Chattfunktionen är ett internt kommunikationsverktyg för teamet. Den är tillgänglig både i Desktop CRM och i Remote-appen, vilket gör att kontor och fältpersonal kan kommunicera i samma kanal.
- Projektkanaler — ett chattrum per projekt
- Direktmeddelanden mellan teammedlemmar
- Olästa meddelanden visas som badge i sidomenyn
- Medarbetare med status "Inaktiv" döljs från chattlistan
Personal & Leverantör
Desktop CRMPersonal

Personalregistret samlar alla medarbetare med roller, kontaktuppgifter och tillgänglighet. Personaldata synkroniseras med Kalender och Remote-appen.
- Roller: Admin, Projektledare, Tekniker, Fältpersonal
- Status: Aktiv / Inaktiv (inaktiva döljs i chatt och kalender)
- Tilldelning av händelser i Kalender
- Åtkomst till Remote-appen konfigureras här (se Remote → Autentisering)
Tabell: personal · IPC: db:personal:list
Leverantör

Leverantörsregistret lagrar kontaktuppgifter för underleverantörer och materialleverantörer. Leverantörer kopplas till order och materialkostnadsposter.
- Namn, organisationsnummer, kontaktperson
- E-post och telefon
- Koppling till order och materialposter
Tabell: leverantorer · IPC: db:leverantorer:list
Inställningar
Desktop CRM
Inställningsmodulen är kontrollpanelen för hela systemet. Ändringar träder i kraft omedelbart utan att appen behöver byggas om.
Branding
Företagsnamn, logotype, primärfärg
E-post
Zoho Mail-konfiguration och SMTP
Personal & åtkomst
Lägg till/ta bort Remote-användare
AI-modeller
API-nycklar för Claude, GPT, Gemini
Säkerhet
Supabase RLS-regler och sessioner
Tabell: app_installningar
AI Workflows
Desktop CRM
AI Workflows är en visuell nodeditor för att bygga automatiserade processer utan programmering. Koppla samman datakällor, AI-modeller och åtgärder i ett flöde.
Stödda AI-modeller
- Anthropic Claude (Haiku, Sonnet, Opus) — rekommenderas för offertgenerering
- OpenAI GPT-4 / GPT-4o
- Google Gemini Pro
Exempelarbetsflöden
SKAPA-OFER
Analyserar projektbeskrivning och genererar komplett offertunderlag med faser och prissättning
GRANSKA-OFFERT
Granskar ett existerande förslag och föreslår förbättringar baserat på historiska projekt
PROJEKTSTATUS
Sammanfattar projekthistorik och nuläge i ett strukturerat dokument för revisor eller kund
KUNDMAIL
Genererar kundanpassad e-post vid statusändringar i projekt eller faktura
Vad är Remote?
RemoteBRF Solbacken
Källarrenovering
Lindblom Bygg
Fasadrenovering
Vasarenen Sverige
Tillbyggnad – Vänaport 8
Axel Norberg
Omläggning – Sörengen 63
Erik Ström
Altan – Tegnergatan 95
Remote är en Next.js-webbapp optimerad för mobil. Den riktar sig till tekniker, hantverkare och projektledare som arbetar ute på fältet och behöver tillgång till kalender, chat och projektinformation — utan att behöva öppna Desktop CRM.
Remote delar samma Supabase-databas som Desktop CRM. Ändringar som görs i Remote syns omedelbart i Desktop CRM och vice versa.
Kalender
Veckovy, markera händelser som slutförda
Chat
Projektkanaler och direktmeddelanden
Personal
Teamöversikt och tillgänglighet
Remote — Installation
RemoteRemote är ett separat Next.js-projekt som hostas oberoende av Desktop CRM. Det kan deployas på Vercel, Hostinger VPS eller Railway.
Hämta källkoden
git clone https://github.com/rankgnar/crm-remote
cd crm-remote
npm installMiljövariabler
NEXT_PUBLIC_SUPABASE_URL=https://<ditt-projekt-ref>.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=<din-anon-nyckel>Remote använder bara ANON_KEY med RLS-policys för åtkomststyrning. Ingen service key exponeras i webbappen.
Deploy till Vercel
npm run dev # Lokalt på port 3000
# Produktion
npx vercel --prodDeploy till Hostinger VPS
# På servern (Node.js 20+ krävs)
npm run build
# Starta med PM2
npm install -g pm2
pm2 start npm --name "remote" -- start
pm2 save && pm2 startupremote.dittforetag.se) så att personalen kan bokmärka adressen på sin telefon.Remote — Autentisering
RemoteInloggning till Remote sker via Supabase Auth. En medarbetare får åtkomst enbart om deras e-postadress finns registrerad i tabellen app_admins.
Lägg till en Remote-användare
- 1Öppna Desktop CRM → Inställningar → Personal
- 2Välj medarbetaren och aktivera "Åtkomst till Remote"
- 3Ange medarbetarens e-postadress (samma adress de använder för att logga in)
- 4Spara — systemet skapar automatiskt en post i app_admins
- 5Medarbetaren får ett välkomstmejl med inloggningslänk
is_app_admin() kontrollerar åtkomsten i databasen. Även om en användare känner till Supabase URL kan de inte läsa data utan att finnas i app_admins.Remote — Funktioner
RemoteKalender
Fältpersonalen ser sin personliga veckokalender med alla händelser tilldelade till dem. Händelser kan markeras som slutförda direkt från telefonen.
Chat
Samma chattfunktion som i Desktop CRM — projektkanaler och direktmeddelanden. Olästa meddelanden visas som badge vid ikonen. Medarbetare med status "Inaktiv" döljs från chattlistan.
Kunder
En förenklad kundöversikt för att snabbt hitta kontaktuppgifter och projektadress ute på fältet. Redigering sker i Desktop CRM.
Personal
Teamöversikt med tillgänglighet och kontaktuppgifter. Synkroniseras i realtid med Desktop CRM.
Vad är Anställdappen?
AnställdappIncheckning
Utcheckning
Rast
Projekt
Anställdappen är en mobiloptimerad webb-app för fältpersonal — tekniker, hantverkare och andra medarbetare som arbetar ute på arbetsplatser. Den är enklare och mer fokuserad än Remote: en anställd behöver bara se sitt schema, sina uppgifter och kommunicera med teamet.
Appen är lokaliserad på svenska, engelska, spanska och polska (SV / EN / ES / PL) för att täcka mångspråkiga team inom bygg och hantverk.
Schema
Dagens och veckans uppgifter i en enkel listvy
Uppgifter
Markera uppgifter som påbörjade eller slutförda
Chatt
Projektkanaler och direktmeddelanden med teamet
Flerspråkigt
SV / EN / ES / PL — väljs automatiskt från webbläsare
Anställdapp — Installation
AnställdappAnställdappen är ett separat Next.js-projekt med next-intl för flerspråksstöd. Deployas på Vercel, Hostinger VPS eller annan Node.js-plattform.
Hämta källkoden
git clone https://github.com/rankgnar/crm-app
cd crm-app
npm installMiljövariabler
NEXT_PUBLIC_SUPABASE_URL=https://<ditt-projekt-ref>.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=<din-anon-nyckel>Deploy till Vercel
npm run dev # Startar på port 3000
# Produktion
npx vercel --prodDeploy till Hostinger VPS
# På servern (Node.js 20+ krävs)
npm run build
# Starta med PM2
npm install -g pm2
pm2 start npm --name "crm-app" -- start
pm2 save && pm2 startuppersonal.dittforetag.se). Appen fungerar som en PWA och kan öppnas offline för att läsa scheman som cachats tidigare.Anställdapp — Autentisering
AnställdappInloggning sker via Supabase Auth med e-post och lösenord. En anställd får åtkomst enbart om deras e-postadress är registrerad i personalregistret i Desktop CRM.
Lägg till en anställd
- 1Öppna Desktop CRM → Personal
- 2Skapa eller välj medarbetaren
- 3Ange e-postadress och aktivera "Åtkomst till Anställdapp"
- 4Medarbetaren får ett välkomstmejl med länk för att sätta lösenord
- 5Vid första inloggning väljer medarbetaren sitt föredragna språk
Anställdapp — Funktioner
AnställdappSchema
Den anställde ser sina tilldelade händelser från Kalendermodulen i Desktop CRM — uppgifter, besök och leveranser för dag och vecka. Vyn är avsiktligt enkel: datum, tid, plats och beskrivning.
Uppgifter
Uppgifter kan markeras som påbörjade eller slutförda direkt i appen. Statusen synkroniseras i realtid till Desktop CRM och syns i Kalendermodulen.
Chatt
Samma chattinfrastruktur som Desktop CRM och Remote — projektkanaler och direktmeddelanden. Den anställde ser bara kanaler kopplade till projekt de är tilldelade.
Flerspråkigt gränssnitt
Gränssnittet detekterar automatiskt webbläsarens språk och väljer bland SV, EN, ES och PL. Den anställde kan byta språk manuellt i inställningar. All affärsdata (kundnamn, projektnamn) visas som den lagrats — ingen maskinöversättning av innehåll.
Vad är Kundportalen?
KundportalTillbyggnad – Vänaport 8
Tidplan
Arbetsplats
Bilder
Kontakt
Anna Lindqvist
Telefon
+46 70 123 45 67
Kundportalen är en autentiserad webbapp där dina kunder kan följa sina projekt, granska offerter och kommunicera med ditt företag. Den är designad för mobil i första hand — mer än 90 % av kunder öppnar portalen från sin telefon.
Portalen är lokaliserad på svenska, engelska och spanska (SV / EN / ES) med automatisk språkidentifiering baserad på webbläsarinställning.
- Projektöversikt med status och tidslinje
- Offertgranskning — läs och godkänn/avvisa
- Direkt kommunikation med företaget via meddelandefunktion
- Mobil-first design, 360 px uppåt
Kundportal — Installation
KundportalKundportalen är ett Next.js 16-projekt med next-intl för flerspråksstöd. Deployas på Vercel, Hostinger VPS eller annan Node.js-plattform.
Hämta källkoden
git clone https://github.com/rankgnar/open-crm-client-v2
cd open-crm-client-v2
npm installMiljövariabler
NEXT_PUBLIC_SUPABASE_URL=https://<ditt-projekt-ref>.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=<din-anon-nyckel>Deploy till Vercel
npm run dev # Startar på port 3000
# Produktion
npx vercel --prodDeploy till Hostinger VPS
# På servern (Node.js 20+ krävs)
npm run build
# Starta med PM2
npm install -g pm2
pm2 start npm --name "kundportal" -- start
pm2 save && pm2 startupis_kund_user_for()-policyn är aktiv på alla relevanta tabeller.Kundportal — Autentisering
KundportalKunder autentiseras via Supabase Auth. En kund får åtkomst enbart om deras e-postadress är registrerad i tabellen kund_users och kopplad till rätt kund i kunder-tabellen.
Bjud in en kund till portalen
- 1Öppna Desktop CRM → Kunder → Välj kunden
- 2Klicka "Bjud in kund till portal"
- 3Ange kundens e-postadress
- 4Systemet skapar en post i kund_users och skickar ett inbjudningsmejl
- 5Kunden klickar länken i mejlet och sätter ett lösenord
is_kund_user_for(kund_id) garanterar att varje kund bara ser sin egen data — även om de försöker manipulera URL-parametrar ser de ingenting från andra kunder.Kundportal — Funktioner
KundportalProjektöversikt
Kunden ser alla sina projekt med status, tidslinje och kortfattad beskrivning. Projektdetaljer uppdateras i realtid från Desktop CRM.
Offerter
Kunden kan läsa fullständiga offertdokument i portalen och välja att godkänna eller avvisa. Godkännande i portalen skickar kunden till Signeringsportalen för digital underskrift.
Meddelanden
Direkt kommunikation mellan kund och företag via ett inbyggt meddelandesystem. Meddelanden från portalen visas i Desktop CRM under kundens profil.
Signeringsportal — Installation
SigneringSigneringsportalen är ett fristående Next.js-projekt. Deployas på Vercel, Hostinger VPS eller annan Node.js-plattform.
Hämta källkoden
git clone https://github.com/rankgnar/crm-sign
cd crm-sign
npm installMiljövariabler
NEXT_PUBLIC_SUPABASE_URL=https://<ditt-projekt-ref>.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=<din-anon-nyckel>
SUPABASE_SERVICE_ROLE_KEY=<din-service-role-nyckel>Signeringsportalen kräver SERVICE_ROLE_KEY för server-side PDF-generering och signaturstämpling — nyckeln exponeras aldrig i klientkoden.
Deploy till Vercel
npm run dev # Startar på port 3000
# Produktion
npx vercel --prodDeploy till Hostinger VPS
# På servern (Node.js 20+ krävs)
npm run build
# Starta med PM2
npm install -g pm2
pm2 start npm --name "crm-sign" -- start
pm2 save && pm2 startupsign.dittforetag.se). Länken som skickas till kunden innehåller ett unikt token knutet till den domänen.Signeringsflöde
SigneringDemo Bygg AB — Erik Ström Håkansson
Signera digitalt
Erik Ström Håkansson
Signeringsportalen är en fristående webbapp för att ta emot och signera offerter digitalt. Kunden behöver inget konto — offerten levereras via en unik engångslänk som skickas från Desktop CRM.
Fullständigt signeringsflöde
- 1
Desktop CRM genererar länk
Administratören klickar "Skicka för signering" på ett förslag. Systemet genererar en unik URL med begränsad giltighetstid och skickar ett e-postmeddelande till kundens adress.
- 2
Kunden öppnar länken
Signeringsportalen laddar offertdokumentet från länkens token. Ingen inloggning krävs. Länken kan bara användas en gång.
- 3
Granskning
Kunden läser igenom offerten med alla faser, rader och priser. Dokumentet kan scrollas och zoomstas.
- 4
Digital signatur
Kunden klickar "Signera" och bekräftar sitt namn. Inga plugin, inga certifikat — signaturens autenticitet garanteras av systemets metadata.
- 5
Stämpling & arkivering
Signaturen stämplas med exakt tidsstämpel (UTC), kundens IP-adress och en kryptografisk hash av dokumentinnehållet. PDF genereras och arkiveras.
- 6
Bekräftelse till båda parter
Det signerade PDF-dokumentet skickas automatiskt till kundens och företagets e-postadress. Förslaget uppdateras till status "Signerat" i Desktop CRM.
Signering — Teknisk detalj
SigneringLänkens livslängd
Signeringslänkar har en konfigurerbar TTL (time-to-live). Standardvärdet är 72 timmar. Om länken löper ut utan signering kan administratören generera en ny från samma förslag i Desktop CRM — det ursprungliga dokumentet ändras inte.
Dokumenthash
När signaturlänken genereras beräknas en SHA-256-hash av offertdokumentets innehåll och sparas i databasen. Samma hash beräknas vid signeringstillfället och jämförs — om dokumentet har manipulerats under resans gång avvisas signaturen.
Vad sparas i databasen
- Signaturdatum och exakt tid (UTC)
- Signatärens namn (som de angivit)
- IP-adress vid signeringstillfället
- SHA-256-hash av dokumentinnehållet
- URL till arkiverat PDF-dokument
Vad är Formulärappen?
FormulärappFrågeformulär
Badrumsrenovering Lidingö
1. Vad är badrummets yta?
8,5 m²
2. Befintliga kakel att ta bort?
Ja
3. Önskat material
Storformat klinker
Formulärappen är en mobiloptimerad webbapp för att samla in strukturerad information från kunder innan offerten skrivs. Administratören genererar ett formulär med AI direkt från projektvyn i Desktop CRM, kopierar eller skickar länken via e-post till kunden, och kundens svar läses sedan automatiskt av AI-offertflödet.
Formulärappen kräver ingen inloggning — kunden öppnar länken och fyller i svaren i sin telefon. Inga cookies, inga konton.
AI-genererade frågor
Formuläret skapas av en konfigurerbar AI-assistent baserat på projektkontexten
Ingen inloggning
Kunden öppnar en unik länk — formuläret är giltigt tills det besvaras
Svar → offert
Svaren sparas och läses direkt av AI-offertflödet när offerten genereras
Formulärapp — Installation
FormulärappFormulärappen är ett Next.js-projekt utan autentisering. All dataåtkomst sker via anonyma Supabase RPCs med SECURITY DEFINER — ingen service role key behövs i webbappen.
Hämta källkoden
git clone https://github.com/rankgnar/open-crm-form
cd open-crm-form
npm installMiljövariabler
NEXT_PUBLIC_SUPABASE_URL=https://<ditt-projekt-ref>.supabase.co
NEXT_PUBLIC_SUPABASE_ANON_KEY=<din-anon-nyckel>Formulärappen exponerar enbart ANON_KEY. Inga sekretnycklar används — all känslig logik hanteras server-side i Supabase Edge Functions.
Deploy till Vercel
npm run dev # Startar på port 3000
# Produktion
npx vercel --prodFormulärappen bör ha en dedikerad domän, t.ex. form.dittforetag.se. Domänen konfigureras i Desktop CRM under Inställningar → Allmänt → Formulärappens URL — systemet använder den för att bygga länkarna som skickas till kunder.
Formulärapp — Funktioner
FormulärappGenerera formulär med AI
I Desktop CRM, under Projekt → Frågor, klickar administratören Generera med AI. En konfigurerbar AI-assistent (typen Formulärgenerator) skapar ett JSON-formulär med relevanta frågor baserade på projektnamnet och eventuell beskrivning. Frågorna kan redigeras manuellt innan formuläret sparas.
Skicka länken
När formuläret är sparat visas en unik länk i formatet form.dittforetag.se/f/{token}. Länken kan kopieras direkt eller skickas via e-post med ett klick — systemet förifyller avsändare, mottagare (kundens e-postadress) och ämnesrad via e-postmallen Frågeformulär — länk till klient. Sändningen loggas i projektets Anteckningar.
Kunden svarar
Kunden öppnar länken och möts av en välkomstskärm med företagsnamn och projektnamn. Formuläret visas sedan fråga för fråga. När kunden skickar svaren sparas de i databasen och en notifikation skickas till företagets e-post via Supabase Edge Function. Svarstillfället loggas som en grön anteckning i projektets Anteckningar.
Svar i AI-offertflödet
Svaren sparas som en .md-fil i projektets dokumentbibliotek (mapp questions). AI-offertflödets data:projekt:text-files-nod läser automatiskt dessa filer — svaren vägs in i offertgenereringen utan manuell handpåläggning.
Notifikationer
E-postmallar för formulärflödet hanteras under Inställningar → E-post → Mallar:
- "Frågeformulär — länk till klient" — mallen för e-posten som skickas till kunden med formulärlänken
- "Formulär besvarat — notifikation" — notifikation till företaget när kunden har svarat. Kan avaktiveras med toggle.
Systemöversikt
open-crm är en Electron-app med strikt separation mellan React-renderer och Node.js main-process. Supabase-klienten är aldrig tillgänglig i renderer — all dataåtkomst sker via IPC-kanaler.
Renderer (React + TypeScript + Tailwind)
└─ window.api.invoke('db:kunder:list')
│ contextBridge
Preload (src/preload/index.ts)
│ ipcRenderer → ipcMain
Main (src/main/ipc/*.ts)
│
Supabase SDK (src/main/supabase.ts)
│
PostgreSQL (Supabase Cloud / self-hosted)Renderer
React 18 + TypeScript 5 + Tailwind CSS v4
Main
Node.js + Electron IPC handlers (src/main/ipc/)
Databas
Supabase PostgreSQL med RLS-policys
@supabase/supabase-js direkt. Alla anrop till databasen måste gå via window.api.invoke(). Detta säkerställer att service key och access token aldrig exponeras i renderer-kontexten.IPC-mönster
Alla IPC-kanaler följer konventionen db:<entitet>:<åtgärd>.
// Hämta alla kunder
const kunder = await window.api.invoke('db:kunder:list') as Kund[]
// Skapa ny kund
const kund = await window.api.invoke('db:kunder:create', {
namn: 'Acme AB',
epost: 'info@acme.se',
}) as Kund
// Uppdatera
await window.api.invoke('db:kunder:update', { id: kund.id, namn: 'Acme AB (uppdaterad)' })// src/main/ipc/kunder.ts
export function registerKunderHandlers(): void {
ipcMain.handle('db:kunder:list', async () => {
const { data, error } = await supabase
.from('kunder')
.select('*')
.order('created_at', { ascending: false })
if (error) throw new Error(error.message)
return data
})
ipcMain.handle('db:kunder:create', async (_, input: CreateKundInput) => {
const { data, error } = await supabase
.from('kunder')
.insert(input)
.select()
.single()
if (error) throw new Error(error.message)
return data
})
}Felhantering
Handlers kastar ett vanligt Error vid fel — inga wrapper-objekt. Renderer-komponenter fångar felet med try/catch och visar det i UI:t.
Databas & RLS
Tabellnomenklatur
Alla tabeller använder snake_case och pluralis. Kolumner är konsekvent snake_case. Primärnyckel är alltid id UUID DEFAULT gen_random_uuid().
Migrationssystem
supabase/
└── migrations/
├── 20240101120000_create_kunder.sql
├── 20240102120000_create_projekt.sql
├── 20240103120000_create_forslag.sql
└── ...Filer namnges YYYYMMDDHHMMSS_beskrivning.sql och appliceras i lexikografisk ordning. Varje fil körs exakt en gång — systemet spårar körda filer i tabellen _applied_migrations.
Hela migrationssetet för en fresh installation finns i rankgnar/open-crm-setup — ett separat repo med bootstrapscript för self-hosted Supabase (VPS).
Row-Level Security (RLS)
Alla tabeller har RLS aktiverat. Varje app i ekosystemet har sin egna åtkomstkontroll:
Desktop CRM
Kör med service_role — full åtkomst via main-processen. Aldrig exponerad i renderer.
Remote
is_app_admin() — kontrollerar om auth.uid() finns i app_admins-tabellen.
Anställdapp
Anställd-RLS — åtkomst begränsad till data kopplad till den inloggade medarbetarens personal-ID.
Kundportal
is_kund_user_for(kund_id) — en kund ser bara sin kund-ID:s data.
Signering
Token-baserad åtkomst utan auth — valideras server-side mot signeringstabellen.
Branding & tema
Visuell identitet (företagsnamn, logotype, primärfärg) lagras i tabellen app_installningar och hämtas vid appstart. Ändringar träder i kraft utan ny build.
Dark / Light-tema
Appen startar i dark mode som standard. Användaren kan växla tema via knappen i titelraden. Valet sparas lokalt och återställs vid nästa start.
Säkerhet — känsliga kolumner
Tabellen app_installningar innehåller både publika konfigurationsvärden och känsliga API-nycklar. Supabase RLS är konfigurerat med kolumn-nivå behörighet — anon-rollen kan bara läsa de kolumner som är icke-känsliga. Service-nycklar exponeras aldrig via PostgREST.
Integrationer
Zoho Mail
E-postintegrationen kräver ett Zoho Mail-konto. Alternativt kan vilken SMTP-server som helst konfigureras.
- Konfigureras under Inställningar → E-post
- Inkommande e-post kopplas till kunder via avsändar-e-postadress
- Mallar för offerter, fakturabekräftelser och påminnelser
- SMTP-alternativ: ange host, port, användarnamn och lösenord
Supabase Auth
Supabase Auth hanterar autentisering för Remote och Kundportalen. Desktop CRM autentiseras inte via Auth — den kör med service_role i main-processen.
Miljövariabler — referens
Komplett lista över alla miljövariabler som används i ekosystemet:
| Variabel | App | Beskrivning |
|---|---|---|
| SUPABASE_URL | Desktop | Project URL från Supabase → Settings → API |
| SUPABASE_ANON_KEY | Desktop | Anon/public key — begränsad åtkomst via RLS |
| SUPABASE_SERVICE_KEY | Desktop | Service role key — full åtkomst, används bara i main-processen |
| SUPABASE_ACCESS_TOKEN | Desktop | Personal Access Token — kör SQL-migreringar via Management API |
| NEXT_PUBLIC_SUPABASE_URL | Remote / App / Portal | Samma URL som ovan, exponeras till webbläsaren |
| NEXT_PUBLIC_SUPABASE_ANON_KEY | Remote / App / Portal | Anon key för webb-apparna, RLS skyddar data |
SUPABASE_SERVICE_KEY och SUPABASE_ACCESS_TOKEN får aldrig exponeras i webbläsaren eller i webb-apparna. De tillhör enbart Desktop CRM:s main-process och ska inte ha prefix NEXT_PUBLIC_.Bidra till projektet
open-crm välkomnar bidrag. Öppna ett issue för buggrapporter eller funktionsförslag, eller skicka in en pull request direkt.
Kom igång
# Forka repot på GitHub och klona din fork
git clone https://github.com/<ditt-namn>/open-crm
cd open-crm
npm install
# Skapa en feature-branch
git checkout -b feat/min-forbattring
# Gör dina ändringar och verifiera
npm run typecheck
# Skicka in pull requestKodkonventioner
- TypeScript strict — inga any-typer, inga @ts-ignore
- IPC-kanaler följer mönstret db:<entitet>:<åtgärd>
- Komponenter max ~200 rader — dela upp vid behov
- Inga hårdkodade färger — använd CSS-tokens (bg-bg, text-muted osv.)
- Inga kommentarer som förklarar VAD koden gör — bara VARFÖR när det inte är uppenbart
- npm run typecheck måste passera innan PR öppnas
CLAUDE.md i repots rot. Det är den auktoritativa referensen för kod- och arkitekturstandarder.Licens
open-crm distribueras under MIT License. Du är fri att använda, modifiera och distribuera koden kommersiellt och icke-kommersiellt. Ingen attribution krävs, men uppskattas.
MIT License
Copyright (c) 2024 open-crm contributors
Permission is hereby granted, free of charge, to any person obtaining a copy
of this software and associated documentation files (the "Software"), to deal
in the Software without restriction, including without limitation the rights
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
copies of the Software, and to permit persons to whom the Software is
provided to do so, subject to the following conditions:
The above copyright notice and this permission notice shall be included in all
copies or substantial portions of the Software.
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND.