Rules Hub
Coding Rules Library
Rule priority, scope & exceptions
Use this to align rules with the senior-level structure (P0/P1/P2, scope, exceptions/tradeoffs).
Never pass server secrets or full records into client-rendered props
Sanitize data before returning it from getServerSideProps / Server Components into client props. Server-only tokens, internal fields, and other users' PII embedded in props ship to the browser in the page HTML.
Bad example
| 1 | // pages/profile.tsx |
| 2 | export const getServerSideProps: GetServerSideProps = async (ctx) => { |
| 3 | const session = await getSession(ctx); // contains accessToken, refreshToken |
| 4 | const user = await api.getFullUser(session.userId); // full record incl. email, internalFlags |
| 5 | return { props: { session, user } }; // both serialized into __NEXT_DATA__ |
| 6 | }; |
Explanation (EN)
Everything in `props` is serialized into the page HTML (`__NEXT_DATA__`) and visible via View Source — no devtools needed. Returning `session` ships the access/refresh tokens to the browser; returning the full `user` ships email and internal flags. The code 'runs on the server', but the output is fully public.
Objašnjenje (HR)
Sve u `props` serijalizira se u HTML stranice (`__NEXT_DATA__`) i vidljivo je preko View Source — bez devtools-a. Vraćanje `session` šalje access/refresh tokene u preglednik; vraćanje punog `user` šalje e-mail i interne oznake. Kod se 'izvršava na serveru', ali izlaz je potpuno javan.
Good example
| 1 | // pages/profile.tsx |
| 2 | export const getServerSideProps: GetServerSideProps = async (ctx) => { |
| 3 | const session = await getSession(ctx); |
| 4 | if (!session) return { redirect: { destination: '/login', permanent: false } }; |
| 5 | const user = await api.getFullUser(session.userId); |
| 6 | // explicit projection of client-safe fields only; token stays server-side |
| 7 | return { |
| 8 | props: { |
| 9 | user: { id: user.id, displayName: user.displayName, avatarUrl: user.avatarUrl }, |
| 10 | }, |
| 11 | }; |
| 12 | }; |
Explanation (EN)
Only client-safe fields cross into props; the session/token is used server-side to fetch and is then discarded. The browser receives the minimum needed to render. Authenticated API calls the client later makes should go through your own route handlers that read the cookie server-side, so the token never needs to reach the client.
Objašnjenje (HR)
Samo polja sigurna za klijenta prelaze u props; sesija/token koristi se na serveru za dohvat i potom se odbacuje. Preglednik prima minimum potreban za renderiranje. Autenticirane API pozive koje klijent kasnije radi treba usmjeriti kroz vlastite route handlere koji čitaju kolačić na serveru, tako da token nikada ne mora doći do klijenta.
Exceptions / Tradeoffs (EN)
Public, non-sensitive config (feature flags, public API base URLs) is fine to pass through props. The rule targets secrets, auth tokens, and PII beyond what the page must display.
Iznimke / Tradeoffi (HR)
Javna, neosjetljiva konfiguracija (feature flagovi, javni API base URL-ovi) može se prosljeđivati kroz props. Pravilo cilja tajne, auth tokene i PII izvan onoga što stranica mora prikazati.