Next.js + React + Supabase
Først lager dere en enkel Next-app med Header/Footer. Deretter bygger dere en liten, artig mini-app med Supabase: Kudos-vegg (korte, snille meldinger + emoji).
Trinn 1 — Installer (...dersom du ikke har gjort det)
- 1.1Installer Node LTS fra nodejs.org.
- 1.2Lag en tom mappe på skrivebordet (f.eks. web-prosjekter) og dra mappen inn i VS Code.
- 1.3Åpne terminalen i VS Code: Ctrl + ` (backtick).
- 1.4Test installasjonen:
node -v
npm -v
Hvis du får versjonsnumre (f.eks. v20.x og
10.x), er
alt klart.
Trinn 2 — Opprett nytt Next.js-prosjekt
- 2.1Med mappen fra 1.2 åpen i VS Code-terminalen, skriv:
npx create-next-app my-first-app
Du kan bruke eget navn, men kun små bokstaver
(f.eks.
npx create-next-app my-first-project).
- 2.2Velg disse svarene for enklest mulig start:
✔ Would you like to use TypeScript? No
✔ Would you like to use ESLint? Yes
✔ Would you like to use Tailwind CSS? No (kan være Yes hvis du vil)
✔ Would you like to use `src/` directory? No
✔ Would you like to use App Router? Yes
✔ Would you like to customize import alias? No
- 2.3Gå inn i prosjektmappen og start dev-serveren:
cd my-first-app
npm run dev
Åpne http://localhost:3000 – du skal se Next.js sin velkomstside (React kjører 🎉).
OBS: Hvis dette ikke fungerer, står du sannsynligvis i feil
mappe når du
kjører npm run dev.
Trinn 3 — Lag egne komponenter
Lag en ny mappe components inni prosjektet ditt. Opprett
Header.js og Footer.js inni denne mappen.
A) Header.js
Kopier koden under inn i filen og lagre filen.
export default function Header() {
return (
<header style={{ background: "#000", color: "#fff", padding: "12px 0" }}>
<div style={{ maxWidth: "1024px", margin: "0 auto", padding: "0 16px" }}>
Ditt React-prosjekt
</div>
</header>
);
}
B) Footer.js
export default function Footer() {
return (
<footer style={{ background: "#000", color: "#fff", padding: "12px 0", textAlign: "center" }}>
© 2025 – Mitt andre React-prosjekt
</footer>
);
}
C) Bruk komponentene i app/layout.js
Erstatt all koden i filen med koden under:
import "./globals.css";
import Header from "../components/Header";
import Footer from "../components/Footer";
export const metadata = {
title: "Mitt andre React-prosjekt",
description: "Next.js + React - test",
};
export default function RootLayout({ children }) {
return (
<html lang="no">
<body>
<Header />
<main style={{ background: "#fff", minHeight: "90vh", padding: "24px 0", color: "#111" }}>
{children}
</main>
<Footer />
</body>
</html>
);
}
D) Oppdater app/page.js
Erstatt all koden i filen med koden under:
export default function Home() {
return (
<section style={{ maxWidth: "1024px", margin: "0 auto", padding: "0 16px" }}>
<h1>Velkommen til ditt første React-prosjekt</h1>
<p>Dette er startsiden i Next.js (React).</p>
</section>
);
}
Trinn 4 — Endre globals.css
Next.js-prosjektet har en fil som heter globals.css i app/-mappen.
Dette er global styling som gjelder for hele appen.
A) Åpne filen
Åpne: app/globals.css
B) Slett alt og lim inn dette:
/* Nullstill margin/padding */
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
/* Sett base-font */
body {
font-family: Arial, Helvetica, sans-serif;
background-color: #f7f7f7;
color: #111;
line-height: 1.5;
}
/* Overskrifter */
h1, h2, h3 {
font-weight: 600;
margin-bottom: 12px;
}
/* Standard spacing for seksjoner */
section {
margin-bottom: 32px;
}
Når du lagrer filen, vil siden oppdatere automatisk (hot reload).
Trinn 7 — Supabase mini-app: Kudos-vegg (enkelt og artig)
Mål: Lag en side i Next som lar elevene sende en kort, hyggelig melding + emoji (kudos). Meldingen lagres i Supabase og vises som en liste.
7ALag tabell i Supabase
I Supabase → Table editor eller SQL editor.
create table if not exists public.kudos (
id uuid primary key default gen_random_uuid(),
message text not null,
emoji text not null default '⭐',
created_at timestamp with time zone not null default now()
);
7BInstaller Supabase i prosjektet
npm i @supabase/supabase-js
7CLegg inn env-variabler
Lag .env.local i prosjektrota (samme nivå som
package.json).
NEXT_PUBLIC_SUPABASE_URL=...
NEXT_PUBLIC_SUPABASE_ANON_KEY=...
Etterpå: stopp og start dev-serveren på nytt (Ctrl
+ C, så npm run dev).
7DLag Supabase-klient
Lag fil: lib/supabaseClient.js
import { createClient } from "@supabase/supabase-js";
export const supabase = createClient(
process.env.NEXT_PUBLIC_SUPABASE_URL,
process.env.NEXT_PUBLIC_SUPABASE_ANON_KEY
);
7ELag siden:
app/kudos/page.js
Dette er en client component (state + knappetrykk).
"use client";
import { useEffect, useState } from "react";
import { supabase } from "../../lib/supabaseClient";
export default function KudosPage() {
const [message, setMessage] = useState("");
const [emoji, setEmoji] = useState("⭐");
const [items, setItems] = useState([]);
const [status, setStatus] = useState("");
async function fetchKudos() {
const { data, error } = await supabase
.from("kudos")
.select("*")
.order("created_at", { ascending: false })
.limit(30);
if (error) setStatus("Kunne ikke hente kudos 😕");
else setItems(data || []);
}
useEffect(() => {
fetchKudos();
}, []);
async function addKudos(e) {
e.preventDefault();
setStatus("");
const clean = message.trim();
if (!clean) return setStatus("Skriv en kort kudos først 🙂");
if (clean.length > 80) return setStatus("Maks 80 tegn 🙂");
const { error } = await supabase
.from("kudos")
.insert([{ message: clean, emoji }]);
if (error) return setStatus("Kunne ikke lagre 😕 (sjekk RLS/policy)");
setMessage("");
setEmoji("⭐");
setStatus("Lagret! 🎉");
fetchKudos();
}
return (
<section style={{ maxWidth: "720px", margin: "0 auto", padding: "0 16px" }}>
<h1>Kudos-vegg</h1>
<p>Gi en hyggelig melding til noen i klassen (kort og snill!).</p>
<form onSubmit={addKudos} style={{ display: "flex", gap: "8px", margin: "12px 0" }}>
<select value={emoji} onChange={(e) => setEmoji(e.target.value)}>
<option>⭐</option>
<option>🔥</option>
<option>👏</option>
<option>💡</option>
<option>💚</option>
</select>
<input
value={message}
onChange={(e) => setMessage(e.target.value)}
placeholder="F.eks: Takk for hjelpen i dag!"
style={{ flex: 1, padding: "8px" }}
/>
<button type="submit" style={{ padding: "8px 12px" }}>Send</button>
</form>
{status && <p style={{ marginBottom: "12px" }}>{status}</p>}
<div style={{ display: "grid", gap: "8px" }}>
{items.map((k) => (
<div key={k.id} style={{ background: "#fff", padding: "10px 12px", borderRadius: "8px" }}>
<strong style={{ marginRight: "8px" }}>{k.emoji}</strong>
{k.message}
<div style={{ fontSize: "12px", opacity: 0.7, marginTop: "6px" }}>
{new Date(k.created_at).toLocaleString("no-NO")}
</div>
</div>
))}
</div>
</section>
);
}
7FLegg lenke i Header
I components/Header.js, legg til en lenke til /kudos.
// Eksempel (inne i div-en i Header)
<a href="/kudos" style={{ color: "#fff", textDecoration: "none" }}>Kudos</a>
- Glemte å starte serveren på nytt etter endring i
.env.local. - Feil import-sti til
supabaseClient(sjekk at du harlib/-mappen). - RLS/policy i Supabase blokkerer insert eller select.