Neva — Full Stack Code (Selected Files)
This PDF contains selected full-stack source files for Neva — a golden-black themed professional network
for engineers and designers. It includes core backend and frontend files, Prisma schema, Docker
compose, and key configuration files.
[Link]
# Neva
Neva is a professional network for home-construction engineers and designers.
This PDF includes selected source files (full code available in project canvas).
Quick start:
1. Set env vars in .env
2. Run prisma migrate
3. Start server and client
.[Link]
# .[Link]
DATABASE_URL=postgresql://neva:neva_pass@db:5432/neva_db?schema=public
JWT_SECRET=replace_with_a_secure_random_value
JWT_EXPIRES_IN=7d
PORT=4000
FRONTEND_URL=[Link]
GOOGLE_CLIENT_ID=your_google_client_id
GOOGLE_CLIENT_SECRET=your_google_client_secret
GOOGLE_CALLBACK_URL=[Link]
[Link]
# [Link] (excerpt)
version: '3.8'
services:
db:
image: postgres:15
environment:
POSTGRES_USER: neva
POSTGRES_PASSWORD: neva_pass
POSTGRES_DB: neva_db
volumes:
- db-data:/var/lib/postgresql/data
ports:
- '5432:5432'
server:
build: ./server
environment:
DATABASE_URL: ${DATABASE_URL}
JWT_SECRET: ${JWT_SECRET}
FRONTEND_URL: ${FRONTEND_URL}
GOOGLE_CLIENT_ID: ${GOOGLE_CLIENT_ID}
GOOGLE_CLIENT_SECRET: ${GOOGLE_CLIENT_SECRET}
GOOGLE_CALLBACK_URL: ${GOOGLE_CALLBACK_URL}
ports:
- '4000:4000'
depends_on:
- db
client:
build: ./client
environment:
VITE_API_URL: [Link]
ports:
- '5173:5173'
depends_on:
- server
volumes:
db-data:
prisma/[Link]
// prisma/[Link] (selected)
generator client {
provider = "prisma-client-js"
}
datasource db {
provider = "postgresql"
url = env("DATABASE_URL")
}
model User {
id String @id @default(cuid())
name String
email String @unique
password String?
role Role
title String?
bio String?
location String?
skills String[] @default([])
portfolio String[] @default([])
avatarUrl String?
createdAt DateTime @default(now())
updatedAt DateTime @updatedAt
posts Post[]
messages Message[]
}
model Post {
id String @id @default(cuid())
author User @relation(fields: [authorId], references: [id])
authorId String
title String
content String
createdAt DateTime @default(now())
}
model Message {
id String @id @default(cuid())
sender User @relation("sentMessages", fields: [senderId], references: [id])
senderId String
receiver User @relation("receivedMessages", fields: [receiverId], references: [id])
receiverId String
content String
createdAt DateTime @default(now())
}
enum Role {
ENGINEER
DESIGNER
CLIENT
}
server/src/[Link]
// server/src/[Link] (excerpt)
import express from 'express';
import http from 'http';
import { Server as SocketIOServer } from '[Link]';
import cors from 'cors';
import dotenv from 'dotenv';
import passport from 'passport';
import session from 'express-session';
import authRoutes from './routes/auth';
import userRoutes from './routes/users';
import postRoutes from './routes/posts';
import messageRoutes from './routes/messages';
[Link]();
const app = express();
const server = [Link](app);
const io = new SocketIOServer(server, { cors: { origin: [Link].FRONTEND_URL || '*' } });
[Link](cors({ origin: [Link].FRONTEND_URL || '*', credentials: true }));
[Link]([Link]());
[Link](session({ secret: [Link].SESSION_SECRET || 'neva_session_secret', resave: false, saveUninitialized: false
[Link]([Link]());
[Link]([Link]());
[Link]('/api/auth', authRoutes);
[Link]('/api/users', userRoutes);
[Link]('/api/posts', postRoutes);
[Link]('/api/messages', messageRoutes);
[Link]('connection', (socket) => {
[Link]('socket connected', [Link]);
[Link]('send_message', (payload) => {
[Link]([Link]).emit('receive_message', payload);
});
[Link]('join', (userId) => {
[Link](userId);
});
});
const PORT = [Link] || 4000;
[Link](PORT, () => [Link](`Server listening on ${PORT}`));
server/src/routes/[Link]
// server/src/routes/[Link] (important parts)
import express from 'express';
import bcrypt from 'bcrypt';
import jwt from 'jsonwebtoken';
import { prisma } from '../prismaClient';
import passport from '../auth/googleStrategy';
const router = [Link]();
[Link]('/register', async (req, res) => {
const { name, email, password, role, title, location } = [Link];
try {
const hash = await [Link](password, 10);
const user = await [Link]({ data: { name, email, password: hash, role, title, location } });
const token = [Link]({ id: [Link], email: [Link] }, [Link].JWT_SECRET || 'secret', { expiresIn: process
[Link]({ token, user: { id: [Link], name: [Link], email: [Link], role: [Link] } });
} catch (err) {
[Link](400).json({ message: (err as any).message });
}
});
[Link]('/login', async (req, res) => {
const { email, password } = [Link];
try {
const user = await [Link]({ where: { email } });
if (!user) return [Link](404).json({ message: 'User not found' });
if (![Link]) return [Link](400).json({ message: 'Use OAuth to sign in' });
const ok = await [Link](password, [Link]);
if (!ok) return [Link](401).json({ message: 'Invalid credentials' });
const token = [Link]({ id: [Link], email: [Link] }, [Link].JWT_SECRET || 'secret', { expiresIn: process
[Link]({ token, user: { id: [Link], name: [Link], email: [Link], role: [Link] } });
} catch (err) {
[Link](400).json({ message: (err as any).message });
}
});
// Google OAuth routes
[Link]('/google', [Link]('google', { scope: ['profile', 'email'] }));
[Link]('/google/callback', [Link]('google', { failureRedirect: [Link].FRONTEND_URL || '/', sess
try {
const user = [Link];
const token = [Link]({ id: [Link], email: [Link] }, [Link].JWT_SECRET || 'secret', { expiresIn: process
const redirect = `${[Link].FRONTEND_URL || '[Link]
[Link](redirect);
} catch (err) {
[Link]([Link].FRONTEND_URL || '/');
}
});
export default router;
server/src/auth/[Link]
// server/src/auth/[Link]
import passport from 'passport';
import { Strategy as GoogleStrategy } from 'passport-google-oauth20';
import { prisma } from '../prismaClient';
[Link]((user: any, done) => {
done(null, [Link]);
});
[Link](async (id: string, done) => {
try {
const user = await [Link]({ where: { id } });
done(null, user);
} catch (err) {
done(err as any, null);
}
});
const clientID = [Link].GOOGLE_CLIENT_ID || '';
const clientSecret = [Link].GOOGLE_CLIENT_SECRET || '';
const callbackURL = [Link].GOOGLE_CALLBACK_URL || '';
[Link](new GoogleStrategy({ clientID, clientSecret, callbackURL }, async (accessToken, refreshToken, profile, don
try {
const email = [Link]?.[0]?.value;
if (!email) return done(new Error('No email from Google'), null);
let user = await [Link]({ where: { email } });
if (!user) {
user = await [Link]({ data: { name: [Link] || 'Google User', email, role: 'CLIENT', avat
}
done(null, user);
} catch (err) {
done(err as any, null);
}
}));
export default passport;
client/src/[Link]
// client/src/[Link] (excerpt)
import React, { useEffect, useState } from 'react'
import { motion } from 'framer-motion'
import axios from 'axios'
import SearchBar from './components/SearchBar'
import ProfileCard from './components/ProfileCard'
import OAuthRedirect from './components/OAuthRedirect'
const API = [Link].VITE_API_URL || '[Link]
export default function App() {
const [results, setResults] = useState<any[]>([])
useEffect(() => {
async function load() {
try {
const res = await [Link](`${API}/api/posts`)
setResults([Link] || [])
} catch (e) {
// ignore
}
}
load()
}, [])
return (
<div className="min-h-screen bg-black text-gold-200">
<header className="p-6 flex justify-between items-center border-b border-gold-700">
<motion.h1 initial={{ scale: 0.9 }} animate={{ scale: 1 }} className="text-2xl font-bold text-gold-400">Neva</m
<div className="flex gap-4">
<a href={`${API}/api/auth/google`} className="px-4 py-2 border border-gold-600 rounded flex items-center gap-
<button className="px-4 py-2 bg-gold-500 text-black rounded">Join</button>
</div>
</header>
<main className="p-8">
<section className="mb-8 text-center">
<motion.h2 initial={{ y: 30, opacity: 0 }} animate={{ y: 0, opacity: 1 }} className="text-4xl font-extrabold"
<p className="mt-2 text-gold-200">Search, message, and hire — all in one place.</p>
<SearchBar onSearch={(q) => { /* implement */ }} />
</section>
<section className="grid grid-cols-1 md:grid-cols-3 gap-6">
{[Link](0,6).map((r) => (
<ProfileCard key={[Link]} data={r} />
))}
</section>
</main>
<footer className="p-6 text-center border-t border-gold-700">© {new Date().getFullYear()} Neva</footer>
<OAuthRedirect />
</div>
)
}
client/src/components/[Link]
// client/src/components/[Link]
import React from 'react'
import { motion } from 'framer-motion'
export default function ProfileCard({ data }: { data: any }) {
return (
<[Link] initial={{ opacity: 0, y: 10 }} animate={{ opacity: 1, y: 0 }} className="bg-gradient-to-br from-black
<div className="flex items-center gap-4">
<img src={[Link] || ''} className="w-16 h-16 rounded-full bg-gold-700 flex items-center justify-center"
<div>
<h3 className="text-xl font-bold">{[Link] || [Link] || 'Profile'}</h3>
<p className="text-gold-200 text-sm">{[Link]?.slice?.(0,80) || [Link] || '—'}</p>
</div>
</div>
<div className="mt-4 flex gap-2">
<button className="px-3 py-1 border border-gold-700 rounded">Connect</button>
<button className="px-3 py-1 bg-gold-500 rounded">Message</button>
</div>
</[Link]>
)
}
server/[Link]
// server/[Link] (dependencies excerpt)
{
"dependencies": {
"bcrypt": "^5.1.0",
"cors": "^2.8.5",
"dotenv": "^16.0.0",
"express": "^4.18.2",
"jsonwebtoken": "^9.0.0",
"multer": "^1.4.5-lts.1",
"prisma": "^5.0.0",
"[Link]": "^4.7.0",
"pg": "^8.10.0",
"passport": "^0.6.0",
"passport-google-oauth20": "^2.0.0"
}
}
client/[Link]
// client/[Link] (dependencies excerpt)
{
"dependencies": {
"axios": "^1.4.0",
"framer-motion": "^10.12.2",
"react": "^18.2.0",
"react-dom": "^18.2.0",
"[Link]-client": "^4.7.0"
}
}
Notes & Next Steps
- Full project code (all files) is in the Neva canvas in the chat — copy there for the complete repository.
- To create a runnable project: initialize npm in server and client folders, set .env, run `npx prisma migrate
dev --name init`, then `npm run dev` in both folders.
- If you want the *entire* repository exported into a single PDF (every file, full content), say "full export" and
I'll generate that — it may be large.