Kako izgraditi online zajednicu u Next.js-u

Forum čuva ono što su njegovi članovi napisali. Zajednica koja djeluje živo nudi više toga odjednom. Članovi podijele fotografiju i dobiju odgovor dok su još tu, uđu u sobu da razgovaraju, glasom ili s kamerom, gledaju događaje kluba uživo i izlaze na pozornicu s vlastitim radom, i vide tko je upravo tu. U Next.js aplikaciji svaka od tih stvari veza je koja ostaje otvorena, s mnogo ljudi odjednom.
Ovaj članak prolazi kroz svaki dio koji prava aplikacija za zajednicu treba, na potpunom primjeru koji radi: Community, fotografskom klubu iz našeg vodiča za Next.js, s njegovim kanalima, sobama u koje se može svratiti i događajima uživo. Možete ga isprobati uživo: prijavite se kao Mia, domaćin kluba, i pregled portfolija počinje upravo sada. Otvorite studio i izađite u eter. Zatim otvorite klub u privatnom prozoru kao Ava, gledajte pregled, dignite ruku i izađite na pozornicu.
Što online zajednica treba
- Kanali koji prate tempo. Poruke i fotografije odmah stižu svima koji čitaju, s prikazom tko tipka i reakcijama, i ostaju spremljene za one koji dođu kasnije. Fotografije se otvaraju samo članovima.
- Sobe u koje se svraća. Glasovne sobe i sobe s kamerama i zaslonima, u koje članovi ulaze i iz njih izlaze kad žele, mnogo ljudi odjednom preko medijskih poslužitelja (kako rade medijski poslužitelji). Domaćini koji nekoga mogu utišati ili ukloniti.
- Događaji uživo. Jedan domaćin za sve članove, s chatom i reakcijama pokraj slike, i član kojeg se poziva na pozornicu da pokaže svoj rad (kako radi prijenos uživo u Next.js-u).
- Što se upravo događa. Tko je u kojoj sobi i koji je događaj u eteru, ažurno na svakoj stranici, bez ponovnog učitavanja.
- Tko je tu. Tko je na mreži i način da im se piše ili ih se nazove.
Sve to radi preko veza koje ostaju otvorene dok god je član na web-stranici, a to serverless funkcija ne može održati (zašto i što učiniti). Svaki dio možete izgraditi sami, na websocketima, WebRTC-u i vlastitim medijskim poslužiteljima. Ili pustite da oblak za rad u stvarnom vremenu vodi veze, pozive i prijenose, dok vaš poslužitelj zadržava ono što je stvarno vaše: članove, pravila i podatke. To radi klub, preko WordPlus Clouda.
Primjer: fotografski klub
Članovi dijele fotografije u kanalima da dobiju povratne informacije, kao što su #critique i #trips. Svraćaju u njegove sobe: u Coffee lounge glasom, u Editing hangout s kamerama i zaslonima. Domaćini vode događaje uživo, pregled portfolija ili tečaj noćne fotografije, na kojima članovi izlaze na pozornicu. To je Next.js aplikacija s App Routerom, Better Authom i Postgresom, a njezin dio za rad u stvarnom vremenu stane u nekoliko datoteka. Pet koraka čini je.
1. Kanali s fotografijama, spremljeni na vašem poslužitelju
Svaki kanal je soba nazvana po svojem broju: channel:2. Web-stranica ih deklarira jednom, po tom uzorku, s pravilom tko smije biti u njemu:
const MESSAGES = { history: 50, emit: ['message', 'typing', 'reaction', 'read'], webhook: ['message', 'reaction'] };
realtime.room('channel:{id}', MESSAGES, async (user, _params, room) => mayWrite(user, room));Svaki član smije biti u kanalu, a nitko drugi. Poruke, prikaz tko tipka, reakcije i potvrde čitanja idu sa stranice na stranicu preko WordPlus Clouda, zapečaćeni, a webhookovi message i reaction donose svaki od njih na poslužitelj web-stranice, koji ga sprema u vlastitu bazu podataka. Stranica kanala gotov je chat na toj sobi:
<Chat
rt={useRealtime()}
room={room}
people={people}
messages={`/api/messages?room=${room}`}
upload="/api/files"
accept="image/jpeg,image/png,image/webp,image/gif"
maxFileSize={15 * 1024 * 1024}
/>messages je vlastita ruta web-stranice za starije poruke, koje se učitavaju dok član pomiče razgovor prema gore. upload polju za pisanje daje spajalicu, a prima i fotografije zalijepljene ili ispuštene na chat: svaka odlazi na vlastitu rutu web-stranice čim se odabere, a poruka nosi samo mjesto na kojem se otvara. WordPlus Cloud fotografiju nikad ne vidi. Ruta odlučuje prema pravilu same sobe:
if (!me || !(file instanceof File) || !/^(channel|chat):\d+$/.test(room) || !(await realtime.mayJoin(room, me))) {
return Response.json({ error: 'This photo is not for this conversation.' }, { status: 403 });
}realtime.mayJoin() pokreće isto pravilo kao ulazak u sobu, pa tko smije čitati kanal, smije u njemu podijeliti fotografiju, a nitko drugi. Svaka fotografija otvara se na vlastitoj adresi, koja ponovno provjerava tko je otvara: netko izvan kluba ne dobiva ništa, kakvu god adresu imao.
2. Glasovne sobe o kojima brinu domaćini
Soba je grupni poziv nazvan po svojem broju, lounge:3, u koji svaki član može svratiti. Pravilo domaćine kluba čini njezinim domaćinima:
realtime.groupCalls('lounge:{id}', async (user) => {
if (!(await isMember(user))) return false;
return (await isHost(user)) ? { admin: true } : true;
});Soba se prikazuje na vlastitoj stranici, a u njoj je gumb za ulazak:
<CallSpot rt={rt} call={room} className="h-[calc(100dvh-14rem)] rounded-2xl">
<GroupCallButton rt={rt} room={room} type={kind} title={name}>
{people.length > 0 ? 'Drop in' : `Open ${name}`}
</GroupCallButton>
</CallSpot>type je audio za glasovnu sobu i video za sobu s kamerama. Prije nego što član uđe, CallSpot prikazuje ono što je u njemu: tko je upravo u sobi i gumb. Nakon ulaska poziv zauzima to mjesto: slika svakoga, ili njihove kamere i zasloni, i kontrole. Član ulazi s isključenim mikrofonom i kamerom i uključuje ih iz poziva, pa svraćanje nikad ne otvara mikrofon iznenada. Na drugoj stranici web-stranice soba se nastavlja u prozoru u kutu i vraća se kad se njezina stranica ponovno otvori.
admin: true sve je što domaćinima treba. Na zaslonu domaćina svaka pločica ostalih ima utišavanje i uklanjanje, koje zaslon poziva traži istom rutom, a ona ih prihvaća samo od domaćina.
3. Događaji uživo, s članovima na pozornici
Događaj je prijenos uživo nazvan po svojem broju: event:5. Njegovo pravilo kaže tko je tko: domaćin događaja izlazi u eter, a svaki drugi član gleda:
realtime.streams(
'event:{id}',
async (user, { id }) => {
const event = await eventOf(id);
if (!event || !(await isMember(user))) return false;
return String(user) === event.host ? { role: 'host', quality: '1080p' } : 'viewer';
},
{ stage: true, reactions: true },
);Domaćin izlazi u eter iz vlastitog studija, stranice web-stranice s velikom slikom, ispod nje Go live, a pokraj nje chat i podignute ruke:
<LiveStream
name={`event:${event.id}`}
view="studio-page"
title={event.title}
url={`/events/${event.id}`}
backUrl={`/events/${event.id}`}
/>Stranica događaja svakom članu daje player s njegovim chatom, isti <LiveStream> pod istim imenom. Domaćin može izaći u eter i iz OBS-a, s adresom i ključem koje daje studio. stage: true je pozornica: član digne ruku iz playera, domaćin je vidi pod Guests i poziva ga, a čim član pritisne Join stage, njegova kamera i mikrofon izlaze u eter pokraj domaćina, za sve koji gledaju.
4. Što se upravo događa, na svakoj stranici
Pokraj svake stranice bočna traka pokazuje tko je u kojoj sobi i koji je događaj u eteru, s brojem gledatelja. Web-stranica ne vodi nikakvu tablicu o tome. WordPlus Cloud to zna:
export async function liveNow(): Promise<Map<string, number>> {
const live = new Map<string, number>();
for (const stream of await realtime.listStreams()) {
const event = idIn(stream.name, 'event');
if (event) live.set(event, stream.viewers);
}
return live;
}realtime.listCalls() i realtime.call(name).get() govore isto o sobama i o tome tko je u kojoj. Da sve ostane ažurno, WordPlus Cloud web-stranici šalje webhook svaki put kad netko uđe u sobu ili iz nje izađe, ili kad događaj izađe u eter ili završi. Web-stranica to kaže u sobi kojoj se pridružuje svaka stranica člana, a kad događaj izađe u eter, javlja to svakom članu:
realtime.on('stream.live', async ({ stream }) => {
const id = idIn(stream, 'event');
const event = id ? await eventOf(id) : null;
if (!event) return;
await realtime.to('club').emit('changed');
const everyone = (await members()).map((person) => person.id).filter((person) => person !== event.host);
await realtime.toUser(everyone).emit('live', { event: event.id, title: event.title, host: event.hostName });
});U layoutu svaka stranica čuje oboje:
useRoom('club', { changed: () => router.refresh() });
useUserEvent('live', (data: { event: string; title: string; host: string }) => {
if (path !== `/events/${data.event}`) show({ text: `${data.host} is live: ${data.title}`, href: `/events/${data.event}`, live: true });
});Prvo čini da svaka stranica sama sebe ponovno zatraži od poslužitelja, bez ponovnog učitavanja, pa bočna traka i otvorena stranica ostaju ažurne. Drugo prikazuje obavijest na kojoj god stranici član bio: „Mia is live: Live portfolio review”, koja otvara događaj. group.joined, group.left i stream.ended kažu changed u istoj sobi.
5. Tko je na mreži
WordPlus Cloud zna tko je na mreži: svaka stranica čijeg je člana web-stranica potvrdila čini tog člana prisutnim na mreži, a stranica saznaje tko dolazi i odlazi, bez ikakvog zahtjeva poslužitelju web-stranice:
const { online } = useOnline(people.map((person) => person.id));
const here = people.filter((person) => online[person.id]);
const away = people.filter((person) => !online[person.id]);Popis članova prvo prikazuje one na mreži, svakoga s Message i Call, a pokraj svake stranice layout na isti način navodi klub, s označenim domaćinima. Stranica člana kaže je li na mreži ili kad je posljednji put viđen.
Što dolazi uz to
- Razgovori u dvoje. Stranica člana sadrži vaš razgovor s njim, zajedno s fotografijama, a vaš poziv prikazuje se pokraj poruka.
- Reakcije i chat na svakom događaju, pokraj slike, i izlazak u eter iz OBS-a ili bilo kojeg enkodera koji šalje preko WHIP-a.
- Dijeljenje zaslona u sobi s kamerama, iz kontrola poziva.
- Imena i lica iz vaše aplikacije. Svaka pločica, poruka i pozornica prikazuje ime i fotografiju člana onako kako ih daje
profileweb-stranice, a u WordPlus Cloudu se ne vodi nikakav popis korisnika. - Oduzimanje pristupa. Kad netko napusti klub, pravila od tada kažu ne, a
realtime.call(name).remove(user)odmah ga uklanja iz sobe.
Isprobajte, pa izgradite svoju
U demu uživo klub na jedan dan pripada samo vama, pa što god ondje podijelite ili koga god sretnete, nitko drugi to ne vidi, a događaj ili soba sami završavaju nakon 10 minuta. Ispod svake stranice ploča How this page works prikazuje kod koji je pokreće, korak po korak, s vrijednostima stranice koju imate otvorenu.
Vodič kroz web-stranicu zajednice izgrađuje cijelu web-stranicu i u cijelosti donosi svaku datoteku njezina dijela za rad u stvarnom vremenu. Prijenosi uživo u Next.js-u i Pozivi u Next.js-u pokazuju svaki način da prijenos ili poziv stavite u vlastitu aplikaciju. Za tim umjesto kluba, videokonferencije u Next.js-u izgrađuju sastanke timskog intraneta.
WordPlus Cloud for Apps ima cijenu prema istodobnim vezama, od 1.000 naviše, uz mjesečnu ili godišnju naplatu. S 1.000 veza prijenosi uživo nisu obračunati do 50 gledatelja istodobno, a grupni pozivi do 32 osobe na videu istodobno, pri čemu se osoba samo sa zvukom računa kao pola. Svakih daljnjih 1.000 veza dodaje 20 gledatelja i 12 osoba na videu. Iznad toga svaki dodatni gledatelj ili osoba na videu troši kredit po minuti, prijenos samo dok je u eteru, a pozivi između dviju osoba ne troše ništa. Pogledajte prijenose uživo za aplikacije, videopozive za aplikacije ili cijene za aplikacije. Pitanja o vašoj integraciji? Pišite nam.