NextJS Templates
Rechnungserstellungs-App-Tutorial mit Next.js, Vercel und Back4app
26 min
in diesem tutorial werden wir eine vollständige invoicing app mit next js als frontend, back4app als backend und zusätzlichen diensten wie clerk für die authentifizierung, stripe für zahlungen und resend für e mail benachrichtigungen erstellen diese anleitung führt durch die einrichtung der authentifizierung, das rechnungsmanagement, die zahlungsabwicklung und die bereitstellung auf vercel 1\ voraussetzungen stellen sie vor dem start sicher, dass sie folgendes haben ein back4app konto ( hier anmelden https //www back4app com/ ) ein clerk konto ( clerk io https //clerk dev/ ) für die authentifizierung ein stripe konto ( stripe com https //stripe com/ ) für die zahlungsabwicklung ein resend konto ( resend io https //resend io/ ) für e mail benachrichtigungen node js und npm installiert ( node js installation https //nodejs org/ ) 2\ einrichtung des backends (back4app) 2 1 erstellen eines neuen projekts in back4app melden sie sich bei back4app an und erstellen sie ein neues projekt navigieren sie zum datenbrowser und erstellen sie die folgenden klassen 2 2 datenmodelle (klassen) 2 2 1 benutzer (automatisch von clerk verwaltet) objekt id benutzername e mail 2 2 2 organisation erstellen sie eine klasse namens organisation fügen sie die folgenden spalten hinzu name (string) der name der organisation ownerid (pointer< user>) zeigt auf die benutzer klasse (automatisch von clerk erstellt) mitglieder (array\<pointer< user>>) ein array von benutzern, die zu dieser organisation gehören 2 2 3 kunde erstellen sie eine klasse namens kunde fügen sie diese spalten hinzu name (string) name des kunden e mail (string) e mail des kunden organisationid (pointer) organisation, zu der dieser kunde gehört 2 2 4 rechnung erstellen sie eine klasse namens rechnung fügen sie diese spalten hinzu rechnungsnummer (string) eindeutiger rechnungsbezeichner kunden id (pointer) verweist auf den kunden organisations id (pointer) verweist auf die organisation betrag (number) gesamtbetrag für die rechnung status (string) optionen sind 'entwurf', 'gesendet', 'bezahlt' und 'überfällig' fälligkeitsdatum (date) das fälligkeitsdatum der rechnung artikel (array) die liste der artikel in der rechnung 2 2 5 zahlung erstellen sie eine klasse namens zahlung fügen sie diese spalten hinzu rechnungs id (pointer) verweist auf die zugehörige rechnung betrag (number) zahlungsbetrag stripesessionid (string) die id der stripe sitzung status (string) zahlungsstatus (z b 'ausstehend', 'erfolgreich', 'fehlgeschlagen') 3\ einrichtung des frontends (next js) 3 1 erstellen eines next js projekts beginnen sie mit der einrichtung ihres next js projekts mit typescript, tailwind css und shadcn/ui komponenten npx create next app\@latest invoicing app typescript cd invoicing app npm install tailwindcss postcss autoprefixer npx tailwindcss init 3 2 tailwind css einrichten konfigurieren sie tailwind, indem sie die tailwind config js aktualisieren und die stile zu globals css hinzufügen in tailwind config js module exports = { content \[ ' /pages/ / {js,ts,jsx,tsx}', ' /components/ / {js,ts,jsx,tsx}', ], theme { extend {}, }, plugins \[], }; in styles/globals css @tailwind base; @tailwind components; @tailwind utilities; 3 3 parse sdk und zusätzliche dienste installieren installieren sie die erforderlichen abhängigkeiten für parse, clerk, stripe und resend npm install parse @clerk/clerk next stripe resend 3 4 parse sdk in next js initialisieren in pages/ app tsx , initialisieren sie das parse sdk mit ihren back4app anmeldeinformationen import { clerkprovider } from '@clerk/clerk react'; import parse from 'parse'; parse initialize('your app id', 'your javascript key'); parse serverurl = 'https //parseapi back4app com'; function myapp({ component, pageprops }) { return ( \<clerkprovider> \<component { pageprops} /> \</clerkprovider> ); } export default myapp; ersetzen sie 'your app id' und 'your javascript key' durch ihre back4app anmeldeinformationen 4\ implementierung der benutzeranmeldung 4 1 clerk integration für die authentifizierung richten sie clerk für die authentifizierung ein gehen sie zum dashboard von clerk, erstellen sie eine anwendung und holen sie sich ihre api schlüssel aktualisieren sie ihre env local datei mit den clerk schlüsseln next public clerk frontend api=your clerk frontend api clerk api key=your clerk api key erstellen sie jetzt pages/sign in tsx und pages/sign up tsx für die anmelde und registrierungsfunktionalität mit clerk komponenten in pages/sign in tsx import { signin } from '@clerk/clerk react'; export default function signinpage() { return \<signin />; } in pages/sign up tsx import { signup } from '@clerk/clerk react'; export default function signuppage() { return \<signup />; } 5\ organisation und kundenmanagement 5 1 organisationen erstellen benutzer können organisationen erstellen, die sie besitzen erstellen sie eine seite pages/organizations/new\ tsx zum erstellen neuer organisationen import { usestate } from 'react'; import parse from 'parse'; export default function neworganization() { const \[name, setname] = usestate(''); const handlecreateorganization = async () => { const organization = parse object extend('organization'); const organization = new organization(); organization set('name', name); organization set('ownerid', parse user current()); try { await organization save(); alert('organization created successfully!'); } catch (error) { console error('error creating organization ', error); } }; return ( \<div> \<h1>create new organization\</h1> \<input type="text" value={name} onchange={(e) => setname(e target value)} placeholder="organization name" /> \<button onclick={handlecreateorganization}>create\</button> \</div> ); } 5 2 kunden verwalten erstellen sie eine kundenverwaltungsseite pages/customers/new\ tsx zum hinzufügen neuer kunden import { usestate } from 'react'; import parse from 'parse'; export default function newcustomer() { const \[name, setname] = usestate(''); const \[email, setemail] = usestate(''); const handlecreatecustomer = async () => { const customer = parse object extend('customer'); const customer = new customer(); customer set('name', name); customer set('email', email); customer set('organizationid', parse user current() get('organizationid')); try { await customer save(); alert('customer created successfully!'); } catch (error) { console error('error creating customer ', error); } }; return ( \<div> \<h1>create new customer\</h1> \<input type="text" value={name} onchange={(e) => setname(e target value)} placeholder="customer name" /> \<input type="email" value={email} onchange={(e) => setemail(e target value)} placeholder="customer email" /> \<button onclick={handlecreatecustomer}>create\</button> \</div> ); } 6\ rechnungsverwaltung 6 1 rechnungen erstellen erstellen sie eine seite zur rechnungsstellung pages/invoices/new\ tsx zum generieren neuer rechnungen import { usestate } from 'react'; import parse from 'parse'; export default function newinvoice() { const \[invoicenumber, setinvoicenumber] = usestate(''); const \[amount, setamount] = usestate(0); const handlecreateinvoice = async () => { const invoice = parse object extend('invoice'); const invoice = new invoice(); invoice set('invoicenumber', invoicenumber); invoice set('amount', amount); invoice set('organizationid', parse user current() get('organizationid')); try { await invoice save(); alert('invoice created successfully!'); } catch (error) { console error('error creating invoice ', error); } }; return ( \<div> \<h1>create new invoice\</h1> \<input type="text" value={invoicenumber} onchange={(e) => setinvoicenumber(e target value)} placeholder="invoice number" /> \<input type="number" value={amount} onchange={(e) => setamount(parsefloat(e target value))} placeholder="amount" /> \<button onclick={handlecreateinvoice}>create\</button> \</div> ); } 6 2 rechnungen anzeigen erstellen sie eine seite pages/invoices/index tsx um alle rechnungen mit sortier und filteroptionen anzuzeigen import { useeffect, usestate } from 'react'; import parse from 'parse'; export default function invoiceslist() { const \[invoices, setinvoices] = usestate(\[]); useeffect(() => { const fetchinvoices = async () => { const invoice = parse object extend('invoice'); const query = new parse query(invoice); const results = await query find(); setinvoices(results); }; fetchinvoices(); }, \[]); return ( \<div> \<h1>invoices\</h1> {invoices map(invoice => ( \<div key={invoice id}> \<h2>invoice #{invoice get('invoicenumber')}\</h2> \<p>amount ${invoice get('amount')}\</p> \<p>status {invoice get('status')}\</p> \</div> ))} \</div> ); } 7\ zahlungsabwicklung (stripe integration) 7 1 stripe checkout einrichten um zahlungen zu verarbeiten, integrieren sie stripe in pages/invoices/\[id] tsx , implementieren sie die erstellung des zahlungslinks mit stripe checkout import { userouter } from 'next/router'; import { useeffect, usestate } from 'react'; import stripe from 'stripe'; export default function invoicedetail() { const router = userouter(); const { id } = router query; const \[invoice, setinvoice] = usestate(null); useeffect(() => { if (!id) return; const fetchinvoice = async () => { const invoice = parse object extend('invoice'); const query = new parse query(invoice); query equalto('objectid', id); const result = await query first(); setinvoice(result); }; fetchinvoice(); }, \[id]); const handlepayinvoice = async () => { const stripe = new stripe(process env stripe secret key); const session = await stripe checkout sessions create({ payment method types \['card'], line items \[ { price data { currency 'usd', product data { name `invoice #${invoice get('invoicenumber')}` }, unit amount invoice get('amount') 100, }, quantity 1, }, ], mode 'payment', success url window\ location origin + '/success', cancel url window\ location origin + '/cancel', }); window\ location href = session url; }; if (!invoice) return \<div>loading \</div>; return ( \<div> \<h1>invoice #{invoice get('invoicenumber')}\</h1> \<p>amount ${invoice get('amount')}\</p> \<button onclick={handlepayinvoice}>pay now\</button> \</div> ); } 8\ e mail benachrichtigungen (wiederholungsintegration) 8 1 rechnungs e mails senden richten sie resend ein, um rechnungs e mails an kunden zu senden import { resend } from 'resend'; export default async function sendinvoiceemail(invoiceid) { const resend = new resend(process env resend api key); const invoice = await fetchinvoicedetails(invoiceid); // function to fetch invoice details const customer = await fetchcustomerdetails(invoice customerid); await resend sendemail({ from 'no reply\@invoicingapp com', to customer email, subject `invoice #${invoice invoicenumber}`, html `\<h1>invoice #${invoice invoicenumber}\</h1>\<p>amount ${invoice amount}\</p>`, }); } 9\ bereitstellung auf vercel um die app auf vercel bereitzustellen, installieren sie die vercel cli und stellen sie bereit npm install g vercel vercel konfigurieren sie umgebungsvariablen für clerk, stripe, resend und back4app im vercel dashboard vor der bereitstellung 10\ fazit in diesem tutorial haben wir eine vollständige rechnungs app mit next js erstellt, back4app für das backend integriert, clerk für die authentifizierung, stripe für zahlungen und resend für e mail benachrichtigungen wir haben die benutzer und organisationsverwaltung, die erstellung von rechnungen, die zahlungsabwicklung und die bereitstellung behandelt