PostgreSQL Pro | Database Mastery
1.33K subscribers
1 photo
28 links
🐘 PostgreSQL Mastery Hub

🎯 What you get:
- Daily optimization tips
- Performance guides
- Real-world solutions
- Query debugging help
- Production best practices

📈 Join 500+ developers improving their PostgreSQL skills
Download Telegram
🚀 DECEMBER DAY 1: 312 Developers. 31 Days. Let's Ship.

No more theory. No more planning. Today we build.

Your Day 1 Mission (Complete in 1 Hour):
Step 1: Database (10 minutes)

-- Create your December database
CREATE DATABASE december_project;
\c december_project;

-- Your first table (modify for your project)
CREATE TABLE users (
id SERIAL PRIMARY KEY,
email VARCHAR(255) UNIQUE NOT NULL,
name VARCHAR(255),
created_at TIMESTAMP DEFAULT NOW()
);

-- Verify it works
INSERT INTO users (email, name) VALUES ('[email protected]', 'Day 1');
SELECT * FROM users;
-- See that row? You're shipping!


Step 2: Project Structure (10 minutes)

mkdir my-december-project
cd my-december-project
npm init -y
npm install express pg dotenv

# Create structure
touch server.js .env README.md
echo "DATABASE_URL=postgresql://localhost/december_project" > .env
echo "# Shipping December 2024 🚀" > README.md


Step 3: First Endpoint (20 minutes)

// server.js - Your first working code
const express = require('express');
const { Pool } = require('pg');
require('dotenv').config();

const app = express();
const pool = new Pool({ connectionString: process.env.DATABASE_URL });

app.use(express.json());

app.get('/', (req, res) => {
res.json({ message: 'December Project - Day 1', status: 'shipping' });
});

app.get('/api/users', async (req, res) => {
const result = await pool.query('SELECT * FROM users');
res.json(result.rows);
});

app.post('/api/users', async (req, res) => {
const { email, name } = req.body;
const result = await pool.query(
'INSERT INTO users (email, name) VALUES ($1, $2) RETURNING *',
[email, name]
);
res.json(result.rows[0]);
});

const PORT = 3000;
app.listen(PORT, () => {
console.log(`December Project running on port ${PORT}`);
});


Step 4: Test & Commit (10 minutes)

# Run it
node server.js

# Test it (new terminal)
curl localhost:3000
curl localhost:3000/api/users

# Commit it
git init
git add .
git commit -m "Day 1: Database + API working"

# Share your commit hash below!


🏆 Day 1 Leaderboard (Live):
First to commit: @alex_dev (00:03 UTC!)
Most tables created: @maria_builds (8 tables)
Already deployed: @tom_ships (on Railway!)
Best project name: @sara_codes ("DecemberOrDie")

Current Status:


156 databases created
89 first commits pushed
12 already deployed
3 have users table with data

💬 Day 1 Check-in:
Comment with:


Database created
First endpoint working
Git commit hash
🎯 Tomorrow's goal

🔥 Day 1 Wisdom:
"Line 1 is harder than lines 2-1000. You just wrote line 1."

"A working database with one table beats a perfect plan with zero tables."

"Day 1 is 90% of the battle. You're here. You started."

Tomorrow (Day 2):

Add authentication
Create your core table
Deploy somewhere

Remember: You don't need perfect. You need progress.

Who shipped something today? Drop your commit hash! 🚀

#December #Day1 #PostgreSQL #Shipping #Building

@postgres
4
🔐 DECEMBER DAY 2: Add Auth in 30 Minutes

Yesterday: Database
Today: Authentication
Tomorrow: Your core feature

Pick Your Auth Method:
Option 1: Password Auth (Classic)

npm install bcrypt jsonwebtoken

// Register
app.post('/api/register', async (req, res) => {
const { email, password } = req.body;
const hashedPassword = await bcrypt.hash(password, 10);

const result = await pool.query(
'INSERT INTO users (email, password_hash) VALUES ($1, $2) RETURNING id, email',
[email, hashedPassword]
);

const token = jwt.sign(
{ userId: result.rows[0].id },
process.env.JWT_SECRET || 'december-2024',
{ expiresIn: '7d' }
);

res.json({ user: result.rows[0], token });
});

// Login
app.post('/api/login', async (req, res) => {
const { email, password } = req.body;

const user = await pool.query('SELECT * FROM users WHERE email = $1', [email]);
if (!user.rows[0]) return res.status(401).json({ error: 'Invalid credentials' });

const validPassword = await bcrypt.compare(password, user.rows[0].password_hash);
if (!validPassword) return res.status(401).json({ error: 'Invalid credentials' });

const token = jwt.sign(
{ userId: user.rows[0].id },
process.env.JWT_SECRET || 'december-2024',
{ expiresIn: '7d' }
);

res.json({ token });
});


Option 2: Magic Links (No Passwords!)

// Send magic link
app.post('/api/magic', async (req, res) => {
const token = crypto.randomBytes(32).toString('hex');

await pool.query(
`INSERT INTO magic_tokens (email, token, expires_at)
VALUES ($1, $2, NOW() + INTERVAL '15 minutes')`,
[req.body.email, token]
);

console.log(`Magic link: https://localhost:3000/magic/${token}`);
res.json({ message: 'Check console for magic link' });
});

// Verify magic link
app.get('/magic/:token', async (req, res) => {
const result = await pool.query(
'SELECT email FROM magic_tokens WHERE token = $1 AND expires_at > NOW()',
[req.params.token]
);

if (!result.rows[0]) return res.status(401).json({ error: 'Invalid token' });

// Create/get user and return JWT
const token = jwt.sign({ email: result.rows[0].email }, 'december-2024');
res.json({ token });
});


Protect Your Routes:

const authenticate = (req, res, next) => {
const token = req.headers.authorization?.split(' ')[1];
if (!token) return res.status(401).json({ error: 'No token' });

try {
req.user = jwt.verify(token, process.env.JWT_SECRET || 'december-2024');
next();
} catch {
res.status(401).json({ error: 'Invalid token' });
}
};

// Use it
app.get('/api/me', authenticate, (req, res) => {
res.json({ userId: req.user.userId });
});


🎯 Day 2 Success = 3 Things Work:

Can register/login
Get a token back
Token protects routes

📊 Day 2 Live Stats:

Password auth: 67 devs
Magic links: 23 devs
Still building: 12 devs

Quick Test:
# Register
curl -X POST localhost:3000/api/register \
-H "Content-Type: application/json" \
-d '{"email":"[email protected]","password":"test123"}'


Day 2 Check-in:

Auth working?
🔐 Which method?
⏱️ Time taken?

Tomorrow: Build your ONE core feature

Pro tip: Don't overthink. Basic auth shipped > Perfect auth planned.

Who has auth working? 🔐

#December #Day2 #Auth #Building

@postgres
2🔥2