2025-11-25 08:00:25
CinemaSins is back with their signature “Everything Wrong With…” breakdown, this time tackling the 1978 musical fantasy The Wiz. Riding the hype of Wicked’s return to theaters, they cruise down the yellow brick road, nitpicking plot holes, cheesy moments and questionable special effects in rapid-fire fashion.
Alongside the video, they’re pushing viewers to explore more CinemaSins channels (TVSins, CommercialSins, CinemaSins Podcast Network), fill out a quick poll, support them on Patreon, and follow their social media for all things sinful cinema.
Watch on YouTube
2025-11-25 08:00:17
Everything Wrong With KPop Demon Hunters In 16 Minutes Or Less is a tongue-in-cheek CinemaSins video where Jeremy and the crew gleefully tally up every “sin” in this K-Pop–infused demon-slaying flick. Expect rapid-fire snark, pop-culture references and enough nitpicks to fill a demon’s soul.
Beyond the roast, they’re hustling you to explore Cinemasins.com, hit up their Linktree for polls and Patreon support, and follow spinoff channels (TVSins, CommercialSins, CinemaSins Podcast Network). You can also connect with the writers on Twitter/Instagram and join the community on Discord, Reddit, Instagram and TikTok.
Watch on YouTube
2025-11-25 07:57:37
These 2 posts are just a tiny slice of what I've seen on my Instagram feed just within the past few days. Each post is getting huge engagement and gives some details as to what is going on. A quick read of the comments indicates artists are starting to focus more on sharing music from and driving traffic to their own websites, Bandcamp (which has remained a champion of indie musicians consistently for 17 years now), and other artist-friendly platforms.
2025-11-25 07:52:04
Cloud SQL is a proven foundation for fully managed databases, offering production-ready MySQL, PostgreSQL, and SQL Server database engines without the operational headache. With Cloud SQL, there’s no need to worry about patches, backups, and scaling limits — just connect your app and start building.
Today, we’re announcing new free trial instances designed to help you experience the power of Cloud SQL for MySQL and PostgreSQL, with no upfront commitment. Whether you're a seasoned Google Cloud developer or new to the platform, this 30-day free trial allows you to explore, test, and truly understand the value Cloud SQL brings to your database needs.
There are two editions of Cloud SQL currently available:
You might be familiar with the standard $300 Google Cloud free trial for new users. While that's a fantastic starting point, customers have been asking us for a more specialized offering. They want a dedicated environment to test the full power of Cloud SQL, especially enterprise-grade configurations for Performance, High Availability (HA), and Data Cache. This new trial is our answer.
This trial provides a significantly enhanced experience for customers developing applications on top of Cloud SQL, allowing you to:
This new Cloud SQL free trial is designed for a wide range of users:
We want you to get a comprehensive understanding of Cloud SQL's key value pillars: price-performance, high availability, connectivity, security, observability, ease of manageability, and open-source compatibility. Your free trial instance will be configured to help you explore all of these areas, based on the following database instance:
Not ready to upgrade quite yet? At the end of the 30-day free trial, we automatically suspend your free trial resources, keeping the instance in a "stopped" state for an additional 90 days, at no additional charge. This should give you ample time to upgrade and continue without interruption.
Ready to unlock the full potential of your data with Cloud SQL? Creating your free trial instance is easy. If you’re new to Google Cloud, just sign up for an account and follow the instructions to create your Cloud SQL free trial instance. This exciting offer is available in all Google Cloud regions. Start your free trial and see what Cloud SQL can do for your applications.
2025-11-25 07:51:43
While developing the platform for LiveSpaces, I identified a critical gap in our delivery workflow. As the application grew, our reliance on manual verification and our existing CI/CD checks proved insufficient. We needed a way to streamline release cycles without sacrificing quality.
I took the initiative to build a comprehensive End-to-End (E2E) test suite using Playwright, but I underestimated the complexity. It wasn't just about clicking buttons; it was about handling authentication flows, managing device states, and dealing with third-party integrations securely and reliably.
From authentication flows to device management, every feature presented unique challenges. Here is a retrospective on the architecture I built to solve these bottlenecks, the decisions I made, and the lessons I learned.
This post focuses on advanced patterns and architectural decisions rather than basic installation. I assume you are familiar with the basics of Playwright or similar E2E tools (Cypress, Selenium).
If you are brand new to Playwright, I highly recommend checking out the official documentation first.
Quick Context:
The examples below use:
The Problem: I could not access real email inboxes (Gmail/Outlook) reliably in automated tests. Using real inboxes made the tests slow, flaky, and prone to security blocks.
The Solution: I implemented a smart mocking strategy.
Code Example:
// Mock the verification code endpoint to bypass email delivery
await page.route('**/api/verification/send', route => {
route.fulfill({
status: 200,
body: JSON.stringify({
success: true,
code: '123456' // Fixed mock code for testing
})
});
});
The Problem: Automating third-party providers (Google, Facebook) is often a violation of their Terms of Service. Furthermore, dealing with 2FA, captchas, or external popups leads to incredibly flaky tests.
The Solution: Comprehensive OAuth flow mocking. Instead of visiting the provider, I intercepted the callback that the provider would have sent to our application.
Code Example:
// Mock the OAuth callback
await page.route('**/api/auth/oauth/callback**', route => {
const url = new URL(route.request().url());
// If the app is trying to exchange a token, give it a mock user
if (url.searchParams.has('access_token')) {
route.fulfill({
status: 200,
body: JSON.stringify({
jwt: 'mock_jwt_token',
user: { id: 123, email: '[email protected]' }
})
});
}
});
The Problem: I needed fast feedback loops during development (mocks) but actual verification before deployment (integration). I didn't want to maintain two separate test suites.
The Solution: Dual-mode test files. I designed the tests to auto-detect the presence of an authentication token in the environment variables to decide whether to mock network requests or hit the real backend.
The Logic Flow:
Code Example:
const AUTH_TOKEN = process.env.AUTH_TOKEN;
const USE_REAL_BACKEND = !!AUTH_TOKEN;
test.beforeEach(async ({ page }) => {
if (USE_REAL_BACKEND) {
console.log('Using REAL backend');
// No mocks; allow requests to pass through
} else {
console.log('Using MOCKED mode');
// Apply mocks defined in separate helper files
await applyNetworkMocks(page);
}
});
The Problem: Integration tests running against a real backend leave behind "zombie" data (e.g., created devices), causing subsequent tests to fail due to duplicate name errors or database bloat.
The Solution:
try/finally blocks for guaranteed cleanup within the test.Code Example:
test('should create and manage device', async ({ page, request }) => {
let testDeviceId = null;
try {
// 1. Create test device via API
const response = await request.post(`${API_URL}/devices`, {
headers: { Authorization: `Bearer ${AUTH_TOKEN}` },
data: { name: 'Test Device', code: 'TEST123' }
});
testDeviceId = (await response.json()).data.id;
// 2. Test the UI flow interacting with this device...
await page.reload();
await expect(page.getByText('Test Device')).toBeVisible();
} finally {
// 3. Always cleanup, even if the assertion above fails
if (testDeviceId) {
await request.delete(`${API_URL}/devices/${testDeviceId}`, {
headers: { Authorization: `Bearer ${AUTH_TOKEN}` }
});
}
}
});
The Problem: Third-party components (maps, heavy charts) often load asynchronously. Tests were failing because they tried to interact with elements before they were truly interactive.
The Solution: Utilizing Playwright's Web-First Assertions. Unlike manual timeouts (waitForTimeout), these assertions automatically retry until the condition is met or the timeout is reached.
Code Example:
const mapInput = page.getByTestId('map-input');
// Bad Practice:
// await page.waitForTimeout(1000);
// Best Practice: Wait for state, not time
// This automatically waits for the element to be in the DOM, visible, AND enabled
await expect(mapInput).toBeEnabled({ timeout: 10000 });
// Now safe to interact
await mapInput.click();
The Problem: Modern UI libraries (like Radix UI or Headless UI) often render dropdowns and modals in "portals" at the bottom of the <body> tag, physically outside the component that triggered them.
The Solution:
Code Example:
// The dropdown trigger is in the main container
await page.getByRole('button', { name: 'Options' }).click();
// The menu itself is in a portal at the document root
// We wait for the menu specifically to be visible
const menu = page.getByRole('menu');
await expect(menu).toBeVisible();
// Click the item inside the menu
await menu.getByRole('menuitem', { name: 'Rename' }).click();
Centralizing selectors in reusable classes was the single highest-ROI decision I made. When the UI changed (and it did often), I updated one file instead of 20.
The Architecture:
Code Example:
// pages/AuthPage.js
export class AuthPage {
constructor(page) {
this.page = page;
this.emailInput = page.getByPlaceholder('[email protected]');
this.loginButton = page.getByRole('button', { name: 'Login' });
}
async login(email, password) {
await this.emailInput.fill(email);
await this.loginButton.click();
}
}
Tests without documentation become legacy code the moment they are written. I created 15+ markdown files covering "How to run," "How to mock," and "How to debug." This dramatically reduced onboarding time for future developers and prevented "fear of the test suite."
Testing the "Happy Path" is easy. Testing the "Sad Path" is where value lies. I systematically mocked 404s, 500s, and network timeouts to ensure the UI handled errors gracefully (e.g., showing Toast notifications) rather than crashing.
By using environment variables to switch between Mocks and Real Backends, a single test file serves as both a Unit-like Test (Mocked: fast, stable, deterministic) and an Integration Test (Real: slower, verifies backend contracts).
getByRole and getByText over CSS classes (.btn-primary). This mimics how users find elements and makes tests resilient to styling refactors.finally block or a fixture).waitForTimeout(5000). If you find yourself doing this, you are likely missing a proper state assertion or an await expect(...).If you want to dive deeper into the concepts mentioned here, I recommend these resources:
This post is based on real-world experience building a production E2E suite. All code examples are simplified for clarity.
2025-11-25 07:24:31
For a while now... I've been building APIs. I used to think REST was all I needed. Every API I built was with REST. Simple express routes like /api/auth, /api/v1/auth, /api/users, /api/v1/users, /api/dashboard, /api/etc. It was clean, predictable and I never really saw a reason to ask any questions. After all, I was quite comfortable with it.
Then I started working on a particular project. And it completely changed how I thought about APIs. For those who might be curious... it’s an escrow platform and I had been working on for some time. Yeah... it was kind of my project for my final year as a computer science student. It's a project to help fight the high rate of scams in Nigeria.
The idea was quite simple: Someone wants to buy something expensive — a laptop, phone, whatever. Instead of sending money directly and praying, they send it through the platform. We hold it in escrow. Only release when both parties confirm delivery or service rendered. It's meant to solve the "I sent the money, they blocked me" epidemic that's far too well known.
Does using the blockchain solve this issue? Yes, using the blockchain could solve this perfectly, but facing the reality: some Nigerians still think of "crypto" as a scam. So I was going traditional: Next.js frontend, Node.js backend, Paystack for payments, PostgreSQL + Prisma ORM + Redis, the usual stack and GraphQL API architecture.
That's when things got messy. GraphQL is incredible... until payment provider needs to tell you someone paid.
This is me going from "REST is all I need" → "GraphQL will save me" → "why am I like this." If you don't know what a resolver is, don't worry. I didn't either.
REST is just normal URLs doing normal things.
GET /users/123 → give me user 123
GET /users/123/orders → give me their orders
POST /transactions → create a new transaction
You make many requests, you get fixed responses, you stitch everything together in the frontend. That's it. It's boring but it works. It's reliable. It's what every bank, every payment gateway, every SMS provider uses.
I didn't learn about GraphQL because I wanted to. I learned it because I had to.
About a year ago, I was brought onto a project as the lead frontend developer. Web app, nothing crazy. I was excited.
The backend lead sends me the API documentation. and let me tell you it wasn’t the usual URL to a swagger documentation I was used to; it was the actual Api URL where I first saw what the GraphQL playground/apollo studio looked like.
I opened the URL I see... I stared at it for a solid five minutes. What the hell is a query? What's a mutation? Why is there only one endpoint? Where are the REST routes. I'd heard of GraphQL before. Saw it mentioned on Twitter. Read a blog post once that I didn't finish. But I had never actually used it. And now I was supposed to build an entire frontend with it.
I didn't want to look stupid even though I was told I could ask questions if i had any, so I didn't bother asking too many questions. Just nodded in the meeting like "yeah, GraphQL, cool, got it." Then I went home and googled and chatgpt-ed "what is GraphQL" like my life depended on it.
Learning GraphQL While Building (The Hard Way)
The project forced me to figure it out fast.And honestly? Once I got past the initial "what is happening" phase, it was kind of amazing.
Instead of this:
// Fetch user
const userRes = await fetch('/api/users/123');
const user = await userRes.json();
// Fetch their orders
const ordersRes = await fetch(`/api/users/123/orders`);
const orders = await ordersRes.json();
// Fetch order details for each order
const orderDetails = await Promise.all(
orders.map(order =>
fetch(`/api/orders/${order.id}`).then(r => r.json())
)
);
I could do this:
query GetUserWithOrders($id: ID!) {
user(id: $id) {
name
email
orders {
id
total
status
items {
name
price
}
}
}
}
One request. Everything I needed. No overfetching. No underfetching.
My frontend code got so much cleaner. And from then I became a believer. After that project ended, I started using GraphQL for everything. Rewrote old projects. Told people REST was outdated. Posted about it. I was that guy.
Then: What Is GraphQL? (From Someone Who Was Confused)
GraphQL is one single endpoint (usually /graphql) where you write exactly what you want:
One request. Everything I need. No extra fields. No missing data.
When I first wrote this query for the transaction page on the frontend and saw it return exactly what the UI needed, I actually said "wow" out loud in an empty room.
I became obsessed. Spent some time converting everything to GraphQL. Killing REST endpoints. Writing resolvers. Setting up Apollo. Converting to GraphQL types.
I was convinced I would'nt touch REST for a while.
Then came my escrow project. And I was ready. GraphQL from day one. Beautiful, nested queries. Type safety everywhere. The whole setup.
Until reality hit.
Then I made a test payment.
Paystack needed to tell my server "hey, payment successful, hold the funds."
But Paystack doesn't send GraphQL queries.
They send a plain POST request to a REST endpoint:
POST https://domain.com/webhooks/paystack
Not to /graphql. Just a normal URL with JSON in the body.
Same with Stripe. Same with Termii for SMS delivery reports. Same with literally every external service I needed to integrate. I sat there for two days straight trying to make Apollo Server accept raw webhook payloads and trigger GraphQL mutations internally.
It was absolute hell.
I tried middleware. I tried wrapping REST routes around GraphQL resolvers. I tried some weird hybrid setup that made my code look like an actual spaghetti.
Nothing felt right.
Eventually, at 2 AM on the fourth day, I gave up and wrote this:
router.post('/webhooks/paystack', async (req, res) => {
const signature = req.headers['x-paystack-signature'] as string;
const payload = req.body;
// Verify signature
const hash = crypto
.createHmac('sha512', process.env.PAYSTACK_SECRET!)
.update(JSON.stringify(payload))
.digest('hex');
if (!signature || hash !== signature) {
return res.status(400).json({ status: 'invalid' });
}
// Handle successful payment
const reference = payload?.data?.reference;
if (reference) {
await escrowService.handleSuccessfulPayment(reference);
}
return res.status(200).json({ status: 'success' });
});
export default router;
A plain REST route.
In my "pure GraphQL" app, you could say I felt dirty. Like I' ha betrayed everything I had just learned. But you know what? The money moved. The escrow updated. Users would be able to get their confirmations. It worked. And that's when I finally accepted the truth.
*1. Webhooks from payment/SMS/logistics providers
*
Every payment gateway, SMS provider, logistics company, bank API — they all use REST webhooks. No exceptions. None of them are switching to GraphQL anytime soon. If you want to build, you play by their rules.
*2. External and partner Integrations
*
When other developers want to build on your platform, they expect normal REST URLs. Simple GET and POST requests. Documentation they can understand in five minutes. GraphQL requires explaining queries, mutations, variables, fragments. There's a learning curve. Sometimes you don't want that friction.
3. Caching
GET /transactions/abc123 can be cached by Cloudflare automatically. By browsers. By CDNs.
GraphQL queries are POST requests to /graphql. CDNs don't cache POST requests by default. You need persisted queries, custom hashing, special configuration. Possible? Yes. Simple? Absolutely not.
*4. File Uploads (multer >> GraphQL multipart hell)
*
Uploading ID cards, proof of delivery photos, profile pictures — way easier with multer and REST endpoints. GraphQL can handle file uploads. I tried it once. Gave up after an hour (although i did find a way in a different project i’m working on). Used REST. Life got easier immediately.
*5. Simple Public Endpoints and Health Checks
*
Health checks. Status pages. Metrics endpoints. Public API routes for partners.
REST is perfect here. Clean. Simple. Everyone understands it.
1. Deeply Nested Data
My escrow transaction page needs buyer info + seller info + transaction details + payment records + message history + dispute status + activity logs.
One GraphQL query vs 7-8 REST calls.
On Nigerian internet where connections drop randomly? Those extra round trips aren't just slower. They fail. A lot.
*2. Mobile Performance
*
Building a React Native version. On 2G/3G networks, every request drains battery. Every extra round trip adds seconds to load time. GraphQL's single request model isn't a nice-to-have. It's a requirement.
3. Different Screens, Different Needs
Admin dashboard wants everything. Mobile app only needs 5 fields. User profile needs something else entirely. Same GraphQL query. Different field selections. No new endpoints.
REST? You either overfetch and waste bandwidth, or you create custom endpoints for every screen and drown in maintenance.
*4. Type Safety Everywhere
*
I run graphql-code-generator on my schema.
Get perfect TypeScript types on frontend and backend. Automatically. For free.
No more "wait, is it phone or phoneNumber?" No more guessing response shapes. No more runtime surprises.
The editor knows everything. Autocomplete works perfectly. Refactoring is safe.
This alone saves me hours every week.
Use GraphQL when:
Use REST when:
Integrating with services that only speak REST
Use both when:
Building anything with payment gateways
Which is basically everything I touch now.
For this escrow project (and future serious projects):
For quick side projects:
I was wrong.
GraphQL didn't kill REST. It moved in and took the master bedroom, sure. But REST still handles the gate, the doorbell, the security system, and all the deliveries from the outside world.
They're not enemies. They're roommates. Sometimes they annoy each other, but they make the house work.
And in 2025, if you're building anything real especially in markets where payments and third-party integrations are everything, the winning move is knowing exactly when to use which tool. No purity contests. Just working software that solves real problems.
Starting out, I thought choosing an API architecture was like choosing a religion. You pick one and defend it forever.
GraphQL good, REST bad. Or vice versa.
But building real products in the real world teaches you something else: pragmatism beats purity every single time.
The best architecture is the one that:
• Solves your actual problems
• Works with your actual constraints
• Ships on time
• Doesn't make your life miserable
Sometimes that's pure REST. Sometimes it's pure GraphQL. Usually it's both.
And that's perfectly fine.
Don't stress about GraphQL vs REST.
Seriously. Don't. I wasted weeks worrying about "the right architecture" when I should've just been building. Start simple. Use what you know. REST is fine. GraphQL is fine. Pick one and ship something.
You'll know when you need the other one. The pain will tell you. For me, the pain was making 8 REST calls to load one transaction page. That's when GraphQL made sense. Then the pain was Paystack webhooks not working with my pure GraphQL setup. That's when REST came back.
Let the problems guide your decisions. Not Xthreads. Not Medium articles. Not even this one.
Before I pick an architecture for a new project, I ask:
Am I building the frontend too?
• Yes → GraphQL makes my life easier
• No, it's a public API → REST is probably better
*Do I need to receive webhooks?
*• Yes → I need REST endpoints, no way around it
• No → Pure GraphQL could work
Is the data deeply nested?
• Yes (user → orders → items → reviews) → GraphQL shines here
• No (simple CRUD) → REST is faster to set up
Am I building for mobile?
• Yes → GraphQL saves me from network round trips
• No, just web → Either works fine
Do I care about type safety?
• Yes → GraphQL + Code Generator is incredible
• No → REST with good validation is fine
How much time do I have?
• Tight deadline → Use what I know best, ship fast
• Building for the long term → Set up both properly from day one
These questions cut through all the noise. They force me to think about my actual needs instead of what's trendy.
1. You're allowed to mix them.
Nobody's going to arrest you for having GraphQL and REST in the same codebase. I promise.
Some people online act like mixing them is a crime. It's not. It's just engineering.
2. Start with REST, add GraphQL later if needed.
GraphQL has more setup. More concepts. More tooling.
REST is simpler to start with. Every developer knows it.
If REST starts hurting, then migrate the painful parts to GraphQL. You don't have to rewrite everything at once.
3. Webhooks will force your hand.
If you're building anything with payments, SMS, email delivery, logistics tracking you will need REST endpoints. Plan for this from day one. Don't be like me, fighting reality at 2 AM.
4. The "pure" approach always fails eventually.
I've tried pure REST. Ran into overfetching hell. I've tried pure GraphQL. Ran into webhook hell. Now I use both. My code is "impure." And it works better than ever.
5. Nobody cares about your API architecture except you.
Users don't care if you use REST or GraphQL or both or neither. They care if your app is fast. If it works. If it solves their problem. The tech stack is invisible to them. As it should be.
I'm still in test mode ( i don't think i would though). Haven't gone live yet. But here's what I learned from testing:
1. Verify the webhook signature ALWAYS
Paystack sends an x-paystack-signature header. You hash the payload with your secret key and compare.
If they don't match, reject it. Someone's trying to fake a payment.
const hash = crypto
.createHmac('sha512', process.env.PAYSTACK_SECRET)
.update(JSON.stringify(payload))
.digest('hex');
if (hash !== signature) {
return { status: 'invalid' };
}
2. Webhooks retry. A LOT.
If your endpoint doesn't respond with 200, Paystack retries. Multiple times. So make your webhook handler idempotent. Don't credit the same payment twice. I use the payment reference as a unique key. Check if I've already processed it. If yes, return success without doing anything.
const existingPayment = await this.prisma.payment.findUnique({
where: { gatewayReference: payload.data.reference }
});
if (existingPayment?.status === 'SUCCESS') {
return { status: 'success' }; // Already processed
}
3. Update fast, process later
Don't do heavy processing in the webhook handler. Mark the payment as successful, return 200 immediately, then process in a background job.
Paystack's webhook has a timeout. If you take too long, they assume it failed and retry. I mark it as paid, queue a job in Redis, then let the job handle notifications, etc. Fast response. Reliable processing.
4. Test in production-like conditions
Ngrok is great for local testing, I think I was given a free domain which I usually use to test in dev mode like prod. But also test on a real server with a real domain.
Here's what finally clicked for me:
GraphQL and REST aren't competing solutions to the same problem.
They solve different problems.
GraphQL solves: "My frontend needs flexible, efficient data fetching."
REST solves: "The outside world needs to talk to my server in a standard way."
Once I stopped seeing them as competitors and started seeing them as tools for different jobs, everything made sense.
It's like arguing whether a hammer or a screwdriver is better. Better for what? They're both useful. Use the right one for the job.
I'm still building this escrow platform. Still in test mode with Paystack. Still fixing bugs. Still learning.
Planning to:
• Build the React Native mobile app (GraphQL will shine here)
• Maybe open up a public REST API for other developers later
It's a long journey. But every problem I solve teaches me something new.
And honestly? The hybrid architecture feels right now. It doesn't feel like a compromise anymore. It feels like the correct solution.
Are you team REST? Team GraphQL? Team "I use both and stopped apologizing for it"?What problems have you run into? What made you switch approaches?
I'd genuinely love to hear your story. Drop a comment. Let's talk about this.
Because honestly, I think a lot of us are struggling with the same questions. We're just not talking about it because we're afraid of looking like we don't have it all figured out.
But none of us have it all figured out. We're all just building stuff, breaking stuff, and learning as we go.
And that's fine.
If you take away anything from this article, let it be this:
Use the right tool for the job. Even if that means using multiple tools.
REST isn't dead. GraphQL isn't a silver bullet. They're both just tools.
And the best developers I know? They're not religious about their tools. They're pragmatic.
They use what works. They ship products. They solve real problems for real people.
Everything else is just noise.
So go build something. Use REST. Use GraphQL. Use both. Use neither.
Just build something that works. Something that helps someone. Something you're proud of.
That's what matters.
Building something Let's connect. Seriously. I'm figuring this stuff out as I go, and I'd love to share notes with other builders. You can connect with me on Linkedin and X.
Think I'm completely wrong about something? Tell me. I'm still learning. Maybe you know something I don't. I'm genuinely interested.
Want to see the code? You can find it here on my github. Fyi the code might be a bit of a mess.. ha-ha.
P.S. If you're still putting /api/v1/ or /api/v2/ in every single URL in 2025, we need to talk. There are better ways to handle API versioning. But that's a whole other article.
Thanks for reading. Now go build something.