49 kr
Engångsavgift · Livstidsåtkomst
  • Komplett juridiskt hyresavtal med alla §§
  • Genererar signeringsfärdig PDF
  • Guide för BankID-signering (Scrive, Assently m.fl.)
  • Obegränsat antal kontrakt
  • Fungerar på mobil, surfplatta & dator
Har du redan betalat?
Felaktig kod. Kontrollera kvittot från din betalning.
🔐 Säker betalning via Stripe · Kortbetalning, Apple Pay & Google Pay
✦ Digitalt Kontrakt
Steg 1 av 3
Fyll i kontraktsuppgifter
Alla fält märkta med * är obligatoriska
Avtalsparter
🏠 Hyresvärd PART 1
👤 Hyresgäst PART 2
Hyresobjekt
Hyresvillkor
Övriga villkor & regler
Steg 2 av 3
Granska kontrakt
Kontrollera att alla uppgifter stämmer innan ni signerar
📋 Läs igenom kontraktet noggrant. Om något behöver ändras, gå tillbaka och korrigera uppgifterna.
UTKAST
Steg 3 av 3
Ladda ner & signera med BankID
Ladda ner kontraktet som PDF och signera via valfri BankID-tjänst
1. Ladda ner kontraktet som PDF
📄 Kontraktet genereras nu som en komplett PDF med alla uppgifter ifyllda. Ladda ner den och spara en kopia innan du fortsätter till signering.
hyresavtal.pdf
Redo att laddas ner och signeras
2. Signera med BankID via en av dessa tjänster

Ladda upp PDF:en till valfri tjänst nedan. Båda parter signerar med sitt BankID — helt gratis eller till låg kostnad.

Assently
Svensk tjänst specialiserad på avtalssignering med BankID. Enkel uppladdning och snabb signeringsprocess.
Gratis 14-dagars test · Månadsplan från 199 kr
Öppna Assently →
DocuSign
Globalt ledande signeringstjänst med stöd för BankID via tillägg. Välkänt varumärke som kunder litar på.
Gratis 30-dagars test · Plan från 120 kr/mån
Öppna DocuSign →
Egreement
Enkel och billig svensk e-signeringstjänst med BankID. Perfekt för hyresavtal och standardkontrakt.
Från 0 kr · Pay-per-sign tillgängligt
Öppna Egreement →
Så här gör du — steg för steg
1
Ladda ner PDF:en ovan och spara den på din enhet.
2
Välj en signeringstjänst ovan (vi rekommenderar Scrive för enklaste flödet).
3
Ladda upp PDF:en och lägg till båda parters e-postadresser som signerare.
4
Båda parter signerar via sin BankID-app. Tjänsten skickar en bekräftelse och arkiverar det signerade avtalet åt er.
PDF nedladdad!
Ladda upp PDF:en till valfri BankID-signeringstjänst för att slutföra signeringen.
// ═══════════════════════════════════════════════════════════════════ // BETALSYSTEM – KONFIGURATION // ═══════════════════════════════════════════════════════════════════ // // GÖR SÅ HÄR (5 minuter): // 1. Skapa gratis konto på https://stripe.com // 2. Gå till "Payment Links" → "Skapa länk" → Pris: 49 kr (engångs) // 3. Under "Efter betalning" → välj "Omdirigera till din webbplats" // och ange din sidas URL + ?paid=PAID2026 // (t.ex. https://dinsida.se/hyreskontrakt.html?paid=PAID2026) // 4. Klistra in din Payment Link-URL nedan: // const STRIPE_PAYMENT_LINK = "https://buy.stripe.com/DIN_LANK_HAR"; // Adminkod (alltid giltig, obfuskerad) const _mc = atob("TGl2ZXJwb29sMTIz"); // ═══════════════════════════════════════════════════════════════════ function goToPayment() { if (STRIPE_PAYMENT_LINK.includes("DIN_LANK_HAR")) { alert("⚠️ Stripe-länken är inte konfigurerad ännu.\n\nÖppna filens kod och klistra in din Payment Link från Stripe (se instruktionerna högst upp i script-delen)."); return; } window.location.href = STRIPE_PAYMENT_LINK; } function unlockApp() { document.getElementById('paywall').classList.add('hidden'); try { localStorage.setItem('hyresavtal_unlocked', '1'); } catch(e) {} } async function tryUnlock() { const code = document.getElementById('unlock_code').value.trim(); const errorEl = document.getElementById('unlock_error'); const btn = document.querySelector('.unlock-row .btn'); errorEl.classList.remove('show'); if (!code) return; // Adminkod — valideras lokalt, aldrig mot API if (code === _mc) { unlockApp(); return; } // Visa laddningsindikator btn.textContent = '...'; btn.disabled = true; try { const res = await fetch('/api/validate-code', { method: 'POST', headers: { 'Content-Type': 'application/json' }, body: JSON.stringify({ code: code.toUpperCase() }) }); const data = await res.json(); if (data.valid) { unlockApp(); } else { const msgs = { not_found: 'Koden hittades inte. Kontrollera din stavning.', already_used: 'Denna kod har redan använts. Varje kod är engångsgiltigt — kontakta hyresavtalet@gmail.com vid frågor.' }; errorEl.textContent = msgs[data.reason] || 'Felaktig kod. Kontrollera kvittot från din betalning.'; errorEl.classList.add('show'); } } catch (err) { errorEl.textContent = 'Kunde inte ansluta till servern. Försök igen.'; errorEl.classList.add('show'); } finally { btn.textContent = 'Lås upp'; btn.disabled = false; } } // Auto-upplåsning: om kunden redan betalat tidigare (sparas i localStorage) (function checkAccess() { let alreadyUnlocked = false; try { alreadyUnlocked = localStorage.getItem('hyresavtal_unlocked') === '1'; } catch(e) {} if (alreadyUnlocked) { unlockApp(); } })(); // Enter-tangent i kodfältet document.addEventListener('DOMContentLoaded', () => { document.getElementById('unlock_code').addEventListener('keydown', e => { if (e.key === 'Enter') tryUnlock(); }); }); // ─── STATE ─────────────────────────────────────────────────────────── // (no canvas state needed — PDF handles everything) // ─── NAV STEPS ─────────────────────────────────────────────────────── function setStep(n) { ['panel1','panel2','panel3','panel4'].forEach((p, i) => { document.getElementById(p).classList.toggle('active', i + 1 === n); }); ['step1-nav','step2-nav','step3-nav'].forEach((s, i) => { const el = document.getElementById(s); el.classList.remove('active', 'done'); if (i + 1 === n) el.classList.add('active'); else if (i + 1 < n) el.classList.add('done'); }); window.scrollTo({ top: 0, behavior: 'smooth' }); } function goToStep1() { setStep(1); } function goToStep2() { const req = ['hv_namn','hv_pnr','hv_email','hg_namn','hg_pnr','hg_email','obj_adress','hyra','datum_fran']; let missing = false; req.forEach(id => { const el = document.getElementById(id); if (!el.value.trim()) { el.style.borderColor = 'var(--error)'; missing = true; } else el.style.borderColor = ''; }); if (missing) { alert('Fyll i alla obligatoriska fält (markerade med röd ram).'); return; } renderPreview(); setStep(2); } function goToStep3() { setStep(3); } // ─── GET VALUE ─────────────────────────────────────────────────────── function v(id) { return document.getElementById(id)?.value?.trim() || '—'; } // ─── RENDER PREVIEW ────────────────────────────────────────────────── function renderPreview() { const dateFrom = v('datum_fran'); const dateTill = v('datum_till'); const tillText = dateTill && dateTill !== '—' ? dateTill : 'tillsvidare'; const kontraktstyp = v('kontraktstyp'); const today = new Date().toLocaleDateString('sv-SE'); const dep = v('deposition'); const depText = dep && dep !== '—' ? dep + ' kr' : 'Ingen deposition avtalad'; const bg = v('bankgiro'); const bgText = bg && bg !== '—' ? bg : 'Meddelas separat'; document.getElementById('contract-preview-content').innerHTML = `
UTKAST

HYRESAVTAL

Avseende uthyrning av bostad / lokal

§ 1 – Avtalsparter

Hyresvärd:
${v('hv_namn')}
Personnr / Org.nr:
${v('hv_pnr')}
E-post:
${v('hv_email')}
Telefon:
${v('hv_telefon')}
Adress:
${v('hv_adress')}
Hyresgäst:
${v('hg_namn')}
Personnr:
${v('hg_pnr')}
E-post:
${v('hg_email')}
Telefon:
${v('hg_telefon')}
Adress:
${v('hg_adress')}

§ 2 – Hyresobjekt

Hyresvärden upplåter till hyresgästen följande objekt för bostadsändamål (om annat ej anges):

Adress:
${v('obj_adress')}
Typ:
${v('obj_typ')}
Storlek:
${v('obj_rum')}, ${v('obj_yta')} m²
Våning:
${v('obj_vaning')}
Ingår i hyran:
${v('obj_ingar')}

§ 3 – Hyresperiod

Hyresavtalet gäller ${kontraktstyp} och löper från ${dateFrom} till ${tillText}.

Uppsägningstid är ${v('uppsagningstid')}. Uppsägning ska ske skriftligen.

§ 4 – Hyra och betalning

Hyresgästen ska betala en månadshyra om ${v('hyra')} kr.

Hyran ska vara hyresvärden tillhanda senast ${v('bet_dag')} varje månad.

Betalning sker till: ${bgText}.

Depositionsbelopp: ${depText}. Depositionen återbetalas inom 30 dagar efter hyrestidens slut, förutsatt att hyresrätten är i godtagbart skick och inga obetalda hyror föreligger.

§ 5 – Ordningsregler och skick

Hyresgästen förbinder sig att väl vårda hyresobjektet och dess inventarier. Skador som uppstår till följd av hyresgästens vållande ska ersättas av hyresgästen. ${v('husdjur')}. ${v('rokning')}. ${v('andrahand')}.

§ 6 – Övriga villkor

${v('ovrigt') !== '—' ? v('ovrigt') : 'Inga övriga villkor har angivits.'}

I övrigt gäller hyreslagen (12 kap. jordabalken) samt Hyresnämndens riktlinjer.

§ 7 – Tvistelösning

Tvister med anledning av detta avtal ska i första hand lösas via förhandling. I andra hand kan ärendet hänskjutas till Hyresnämnden eller allmän domstol.

§ 8 – Underskrifter

Avtalet har upprättats i två exemplar, varav parterna tagit var sitt. Underskrifterna bekräftar att parterna tagit del av och godkänner samtliga villkor i detta avtal.

Upprättat: ${today} | Genererat med Hyresavtalet.se

`; } // ─── GENERATE & DOWNLOAD PDF ───────────────────────────────────────── function downloadPDF() { const { jsPDF } = window.jspdf; const doc = new jsPDF({ unit: 'mm', format: 'a4' }); const navy = [27, 43, 75]; const gold = [201, 168, 76]; const gray = [74, 82, 104]; const lgray = [238, 240, 244]; const black = [26, 30, 46]; const W = 210, margin = 18; const contentW = W - margin * 2; let y = 0; // ── Header bar ── doc.setFillColor(...navy); doc.rect(0, 0, W, 36, 'F'); doc.setFillColor(...gold); doc.rect(0, 36, W, 1.2, 'F'); doc.setTextColor(255, 255, 255); doc.setFont('helvetica', 'bold'); doc.setFontSize(20); doc.text('HYRESAVTAL', W / 2, 18, { align: 'center' }); doc.setFont('helvetica', 'normal'); doc.setFontSize(8); doc.setTextColor(180, 190, 210); doc.text('Avseende uthyrning av bostad / lokal · Genererat med Hyresavtalet.se', W / 2, 27, { align: 'center' }); y = 46; // ── Helper functions ── const newPage = () => { doc.addPage(); doc.setFillColor(...navy); doc.rect(0, 0, W, 12, 'F'); doc.setTextColor(180, 190, 210); doc.setFont('helvetica', 'normal'); doc.setFontSize(7); doc.text('Hyresavtalet.se · Fortsättning', W / 2, 8, { align: 'center' }); y = 20; }; const checkY = (needed = 12) => { if (y + needed > 275) newPage(); }; const sectionTitle = (title) => { checkY(14); doc.setFillColor(...navy); doc.rect(margin, y, contentW, 7, 'F'); doc.setTextColor(...gold); doc.setFont('helvetica', 'bold'); doc.setFontSize(7.5); doc.text(title, margin + 3, y + 4.8); y += 11; }; const infoBox = (rows) => { const rowH = 7; const totalH = rows.length * rowH + 4; checkY(totalH + 2); doc.setFillColor(...lgray); doc.roundedRect(margin, y, contentW, totalH, 2, 2, 'F'); const col1 = margin + 3; const col2 = margin + contentW / 2 + 2; rows.forEach((row, i) => { const ry = y + 4 + i * rowH; doc.setFont('helvetica', 'bold'); doc.setFontSize(7.5); doc.setTextColor(...gray); doc.text(row[0], col1, ry); doc.setFont('helvetica', 'normal'); doc.setTextColor(...black); doc.text(row[1] || '—', col2, ry); }); y += totalH + 4; }; const bodyText = (text) => { checkY(10); doc.setFont('helvetica', 'normal'); doc.setFontSize(8.5); doc.setTextColor(...black); const lines = doc.splitTextToSize(text, contentW); lines.forEach(line => { checkY(6); doc.text(line, margin, y); y += 5.5; }); y += 2; }; const highlight = (label, value) => { doc.setFont('helvetica', 'normal'); doc.setFontSize(8.5); doc.setTextColor(...black); return `${label} ${value}`; }; // ── § 1 – PARTER ── sectionTitle('§ 1 – AVTALSPARTER'); infoBox([ ['Hyresvärd:', v('hv_namn')], ['Personnr / Org.nr:', v('hv_pnr')], ['E-post:', v('hv_email')], ['Telefon:', v('hv_telefon')], ['Adress:', v('hv_adress')], ]); infoBox([ ['Hyresgäst:', v('hg_namn')], ['Personnr:', v('hg_pnr')], ['E-post:', v('hg_email')], ['Telefon:', v('hg_telefon')], ['Adress:', v('hg_adress')], ]); // ── § 2 – OBJEKT ── sectionTitle('§ 2 – HYRESOBJEKT'); infoBox([ ['Adress:', v('obj_adress')], ['Typ:', v('obj_typ')], ['Storlek:', `${v('obj_rum')}, ${v('obj_yta')} m²`], ['Våning:', v('obj_vaning')], ['Ingår i hyran:', v('obj_ingar')], ]); // ── § 3 – PERIOD ── sectionTitle('§ 3 – HYRESPERIOD'); const tillText = (v('datum_till') !== '—') ? v('datum_till') : 'tillsvidare'; bodyText(`Hyresavtalet gäller ${v('kontraktstyp')} och löper från ${v('datum_fran')} till ${tillText}. Uppsägningstid är ${v('uppsagningstid')}. Uppsägning ska ske skriftligen.`); // ── § 4 – HYRA ── sectionTitle('§ 4 – HYRA OCH BETALNING'); const bgText = v('bankgiro') !== '—' ? v('bankgiro') : 'Meddelas separat'; const depText = v('deposition') !== '—' ? v('deposition') + ' kr' : 'Ingen deposition avtalad'; bodyText(`Hyresgästen ska betala en månadshyra om ${v('hyra')} kr. Hyran ska vara hyresvärden tillhanda senast ${v('bet_dag')} varje månad. Betalning sker till: ${bgText}.`); bodyText(`Depositionsbelopp: ${depText}. Depositionen återbetalas inom 30 dagar efter hyrestidens slut, förutsatt att hyresrätten är i godtagbart skick och inga obetalda hyror föreligger.`); // ── § 5 – ORDNING ── sectionTitle('§ 5 – ORDNINGSREGLER OCH SKICK'); bodyText(`Hyresgästen förbinder sig att väl vårda hyresobjektet och dess inventarier. Skador som uppstår till följd av hyresgästens vållande ska ersättas av hyresgästen. ${v('husdjur')}. ${v('rokning')}. ${v('andrahand')}.`); // ── § 6 – ÖVRIGT ── sectionTitle('§ 6 – ÖVRIGA VILLKOR'); bodyText(v('ovrigt') !== '—' ? v('ovrigt') : 'Inga övriga villkor har angivits.'); bodyText('I övrigt gäller hyreslagen (12 kap. jordabalken) samt Hyresnämndens riktlinjer.'); // ── § 7 – TVIST ── sectionTitle('§ 7 – TVISTELÖSNING'); bodyText('Tvister med anledning av detta avtal ska i första hand lösas via förhandling. I andra hand kan ärendet hänskjutas till Hyresnämnden eller allmän domstol.'); // ── § 8 – UNDERSKRIFTER ── checkY(70); sectionTitle('§ 8 – UNDERSKRIFTER (BankID)'); bodyText('Avtalet har upprättats i två exemplar, varav parterna tagit var sitt. Underskrift sker digitalt med BankID via separat signeringstjänst. Underskrifterna bekräftar att parterna tagit del av och godkänner samtliga villkor i detta avtal.'); checkY(55); y += 4; // Signature boxes const boxW = (contentW - 8) / 2; const boxH = 36; // Left box – Hyresvärd doc.setDrawColor(...navy); doc.setLineWidth(0.5); doc.roundedRect(margin, y, boxW, boxH, 2, 2); doc.setFillColor(...navy); doc.roundedRect(margin, y, boxW, 7, 2, 2, 'F'); doc.rect(margin, y + 4, boxW, 3, 'F'); doc.setTextColor(255,255,255); doc.setFont('helvetica', 'bold'); doc.setFontSize(7); doc.text('HYRESVÄRD · UNDERSKRIFT', margin + 3, y + 5); doc.setTextColor(...gray); doc.setFont('helvetica', 'normal'); doc.setFontSize(7.5); doc.text(v('hv_namn'), margin + 3, y + 17); doc.text('Personnr: ' + v('hv_pnr'), margin + 3, y + 23); doc.setDrawColor(...lgray); doc.setLineWidth(0.4); doc.line(margin + 3, y + 31, margin + boxW - 3, y + 31); doc.setFontSize(6.5); doc.setTextColor(...gray); doc.text('Signatur via BankID', margin + 3, y + 34.5); // Right box – Hyresgäst const rx = margin + boxW + 8; doc.setDrawColor(...navy); doc.setLineWidth(0.5); doc.roundedRect(rx, y, boxW, boxH, 2, 2); doc.setFillColor(...navy); doc.roundedRect(rx, y, boxW, 7, 2, 2, 'F'); doc.rect(rx, y + 4, boxW, 3, 'F'); doc.setTextColor(255,255,255); doc.setFont('helvetica', 'bold'); doc.setFontSize(7); doc.text('HYRESGÄST · UNDERSKRIFT', rx + 3, y + 5); doc.setTextColor(...gray); doc.setFont('helvetica', 'normal'); doc.setFontSize(7.5); doc.text(v('hg_namn'), rx + 3, y + 17); doc.text('Personnr: ' + v('hg_pnr'), rx + 3, y + 23); doc.setDrawColor(...lgray); doc.setLineWidth(0.4); doc.line(rx + 3, y + 31, rx + boxW - 3, y + 31); doc.setFontSize(6.5); doc.setTextColor(...gray); doc.text('Signatur via BankID', rx + 3, y + 34.5); y += boxH + 8; // ── BankID notice ── checkY(18); doc.setFillColor(232, 241, 255); doc.roundedRect(margin, y, contentW, 14, 2, 2, 'F'); doc.setTextColor(27, 60, 130); doc.setFont('helvetica', 'bold'); doc.setFontSize(7.5); doc.text('Information om BankID-signering', margin + 3, y + 5); doc.setFont('helvetica', 'normal'); doc.setFontSize(7); doc.text('Detta dokument är upprättat för signering med BankID via godkänd e-signeringstjänst (t.ex. Scrive, Assently eller Egreement).', margin + 3, y + 9.5); doc.text('Det signerade avtalet distribueras till båda parter via signeringstjänsten och utgör det juridiskt giltiga originalet.', margin + 3, y + 13); y += 18; // ── Footer ── const today = new Date().toLocaleDateString('sv-SE'); const contractId = 'HYR-' + Date.now(); doc.setFillColor(...navy); doc.rect(0, 287, W, 10, 'F'); doc.setTextColor(150, 165, 200); doc.setFont('helvetica', 'normal'); doc.setFontSize(6.5); doc.text(`Hyresavtalet.se · Upprättat: ${today} · Avtal-ID: ${contractId} · Väntar på BankID-signering`, W / 2, 293, { align: 'center' }); // ── Save ── const fname = 'hyresavtal_' + v('obj_adress').replace(/[^a-zA-Z0-9]/g,'_').substring(0,25) + '.pdf'; doc.save(fname); // Show confirmation document.getElementById('pdf_downloaded_msg').style.display = 'flex'; document.getElementById('pdf_filename').textContent = fname; } // ─── MODALS ────────────────────────────────────────────────────────── function showModal(id) { const tpl = document.getElementById('tpl_' + id); if (!tpl) return; document.getElementById('modal_content').innerHTML = tpl.innerHTML; document.getElementById('modal_overlay').classList.add('open'); document.body.style.overflow = 'hidden'; } function closeModal() { document.getElementById('modal_overlay').classList.remove('open'); document.body.style.overflow = ''; } document.addEventListener('keydown', e => { if (e.key === 'Escape') closeModal(); }); function toggleFaq(el) { const answer = el.nextElementSibling; const isOpen = answer.classList.contains('open'); // Close all document.querySelectorAll('.faq-a').forEach(a => a.classList.remove('open')); document.querySelectorAll('.faq-q').forEach(q => q.classList.remove('open')); if (!isOpen) { answer.classList.add('open'); el.classList.add('open'); } } function startNew() { location.reload(); }