AI 资讯
Extending the Login Session to 1 Year for Kiosk‑Mode TV Screens (Next.js API Route)
Extending the Login Session to 1 Year for Kiosk‑Mode TV Screens (Next.js API Route) TL;DR: I changed the maxAge of the auth cookie from 30 days to 365 days in src/app/api/login/route.ts . The tweak lets a TV kiosk stay logged in without a daily refresh, while keeping the same security flags. The Problem Our kiosk‑mode deployment runs on large‑format TVs that display a live dashboard. The UI is protected by the same JWT‑based authentication we use for the web app. After a user logs in, the server sets a Set-Cookie header with the token: cookie : serialize ( " token " , jwt , { httpOnly : true , secure : true , sameSite : " lax " , path : " / " , maxAge : 60 * 60 * 24 * 30 , // 30 days }); In practice, the TVs are turned on once a week and are expected to stay signed in for months. After 30 days the cookie expires, the dashboard silently redirects to the login page, and a technician has to manually re‑authenticate the device. The symptom was a 401 Unauthorized error after exactly 30 days, logged as: Error: No valid session cookie found (maxAge expired) The root cause: the maxAge value was hard‑coded to 30 days, which is fine for browsers but not for unattended kiosks. What I Tried First My initial thought was to keep the 30‑day limit and simply refresh the token on every API call . I added a middleware that called the login endpoint silently if a request lacked a valid token. The flow looked like this: // pseudo‑middleware if ( ! req . cookies . token ) { await fetch ( " /api/login " , { method : " POST " , body : storedCredentials }); } What went wrong? Rate limiting – The middleware hit the login endpoint on every request that missed a token, quickly exhausting the auth provider's rate limit. State leakage – Storing credentials on the client (even in a server‑side environment) introduced a security surface. Complexity – The extra round‑trip added latency and made the code harder to debug. After a few failed attempts (and a stack trace full of 429 Too Many Requests )
AI 资讯
Automating Daily Bluesky Posts with a JSON‑Driven Content Pipeline
Automating Daily Bluesky Posts with a JSON‑Driven Content Pipeline TL;DR: I added a set of JSON files and a lightweight loader to the content‑automation repo so our CI can generate and publish daily Bluesky posts automatically. The change centralizes multilingual copy, makes the publishing script data‑driven, and removes the manual copy‑paste step that was breaking our release flow. The Problem Our weekly release process includes a short status update on Bluesky. The copy lives in a markdown file that we edit manually, then copy‑paste into the Bluesky CLI. Two issues kept surfacing: Human error – a typo or missing line would cause the post to be rejected by the API ( Error: Invalid payload: missing "text" ). No versioning – we had no way to track which text was used for a given date, making it impossible to audit or rollback a post. The symptom was a failed CI job that stopped the whole pipeline with the error above, and we were forced to roll back the entire release just to fix a missing word. What I Tried First My first attempt was to add a tiny shell script that reads a bluesky.md file and pipes it into the CLI: cat content/2026/08/16/bluesky.md | npx bluesky-cli post That worked locally, but the script crashed in CI because the file path was hard‑coded and the runner didn’t have the bluesky-cli binary installed. I also quickly realized that the same script would need to support English and Spanish versions, so the hard‑coded approach would explode as we added more languages. The Implementation 1. Data‑driven content files Instead of markdown, I switched to a JSON structure that can hold multiple languages and post types (progress, announcement, etc.). Each day gets its own folder under content/YYYY/MM/DD/VS/ . For the 2026‑08‑16 release we added: content/2026/08/16/VS/bluesky_en.json content/2026/08/16/VS/bluesky_es.json content/2026/08/16/VS/metadata.json Example bluesky_en.json [ { "type" : "progress" , "text" : "Finally pushed a real change: coverage for the
AI 资讯
Adding a “Control de Obra” Module to Ventas Desarrollos (NestJS + Next.js)
Adding a “Control de Obra” Module to Ventas → Desarrollos (NestJS + Next.js) TL;DR: I built a brand‑new Construction feature (Control de Obra) inside the Ventas → Desarrollos flow, wiring a NestJS controller, a migration for branding_settings , and a Next.js page. While doing that I also fixed the setToken bug that stopped the BrokerDashboard from refreshing its session. The result is a clean, testable API endpoint and a functional UI component that talks to it. The Problem Our product needed a way for sales teams to track the construction status of each development (obra). The UI already had a “Desarrollos” list, but the backend had no endpoint to create, read, update, or delete construction records. At the same time the BrokerDashboard ( apps/web/src/app/portal-broker/page.tsx ) was failing to refresh the user session after a token rotation. The console showed: Error: setToken is not a function at Object.<anonymous> (src/portal-broker/page.tsx:78:15) Both issues were blockers: No API → the UI could only display static data. Stale token handling → users were logged out unexpectedly after a token refresh. What I Tried First I first tried to reuse the existing VentasPropertiesController ( apps/api/src/ventas/ventas-properties.controller.ts ). The controller was already imported in AppModule , but it was dead code (the class had no routes) and its methods lacked the AuthGuard we use across the API. I added a couple of ad‑hoc routes inside that controller, but: The routes conflicted with the existing /ventas namespace. The controller’s @UseGuards(AuthGuard) was missing, causing 401 errors in the browser. The migration for branding_settings was still out of sync, leading to a “column does not exist” error when the new endpoint tried to read branding data. After a few hours of chasing 404s and 401s, I decided the cleanest path was to create a dedicated module for construction and keep migrations in sync. The Implementation 1. Register the new controller in AppModule // a
AI 资讯
Automating Multi‑Platform Content Publishing with a Node.js Scheduler
Automating Multi‑Platform Content Publishing with a Node.js Scheduler TL;DR: I extended the content-automation repo to generate weekly newsletters, Dev.to articles, and platform‑specific markdown in a single CI run. The key was a tiny Node.js scheduler that reads a JSON manifest, writes files, and flips “generated” flags in metadata.json so downstream pipelines know what to publish. The Problem Our content pipeline had three independent manual steps: Write a weekly newsletter markdown file. Draft a Medium article. Publish a Dev.to post. Each step required copying the same body copy into a different folder ( weekly/ , content-automation/medium_* , content-automation/substack_* ) and then manually toggling flags in metadata.json . During a production run on 2026‑08‑08 the CI job failed with a cryptic log line: Error: Conn The truncated message was coming from the Prisma client that our automation script uses to fetch the latest draft from the CMS. Because the script never updated the metadata.json flags after a successful write, the next run tried to re‑process the same draft, hit a stale DB connection, and blew up. In short: the automation was not idempotent , and the state tracking was brittle. What I Tried First My first attempt was to wrap the whole generation flow in a try / catch and, on any error, abort the job without touching the manifest. I added a quick if (fs.existsSync(filePath)) return; guard to each write operation. // naive guard if ( fs . existsSync ( targetPath )) { console . log ( ` ${ targetPath } already exists – skipping` ); return ; } That prevented duplicate files, but it also silently skipped a legitimate update when we intentionally rewrote a newsletter (e.g., after a typo fix). Moreover, the guard didn’t address the stale Prisma connection, so the same Error: Conn kept surfacing in later runs. The Implementation 1. Central Manifest ( metadata.json ) The manifest now lives at content/2026/08/08/content-automation/metadata.json . I added expli
AI 资讯
Enhancing CI/CD and E2E Testing with Sentry Integration in tvview
Enhancing CI/CD and E2E Testing with Sentry Integration in tvview TL;DR: I integrated Sentry for error tracking and improved End-to-End (E2E) testing in the tvview project, enhancing the CI/CD pipeline. This resulted in a score increase from 85 to 95+. The Problem The tvview project lacked comprehensive error tracking and E2E testing, making it difficult to identify and resolve issues in production. The existing CI/CD pipeline needed improvement to ensure smoother deployments and better code quality. What I Tried First Initially, I focused on setting up E2E tests using Vitest, but encountered issues with the test configuration. I also attempted to integrate Sentry, but faced challenges with the DSN (Data Source Name) configuration. The Implementation Step 1: Configuring Sentry To integrate Sentry, I created separate configuration files for the client, edge runtime, and server: // sentry.client.config.ts import * as Sentry from " @sentry/nextjs " ; Sentry . init ({ dsn : " https://385038c88b6eb6ddac52d05a144ab8c1@o4511628189630464.ingest.us.sent " , // Additional configuration options }); // sentry.edge.config.ts import * as Sentry from " @sentry/nextjs " ; Sentry . init ({ dsn : " https://385038c88b6eb6ddac52d05a144ab8c1@o4511628189630464.ingest.us.sent " , // Additional configuration options }); // sentry.server.config.ts import * as Sentry from " @sentry/nextjs " ; Sentry . init ({ dsn : " https://385038c88b6eb6ddac52d05a144ab8c1@o4511628189630464.ingest.us.sentry.io " , // Additional configuration options }); Step 2: Enhancing CI/CD Pipeline I updated the .github/workflows/ci-e2e.yml file to include Sentry configuration and E2E testing: name : 📺 CI + E2E — TVView on : push : branches : [ main ] workflow_dispatch : {} schedule : - cron : " 35 6 * * *" jobs : build-and-test : runs-on : ubuntu-latest steps : - name : Checkout code uses : actions/checkout@v2 - name : Install dependencies run : npm install - name : Generate Prisma client env : DATABASE_URL : " postgre
AI 资讯
Enhancing CraveView's CI/CD Pipeline with Sentry and E2E Tests
Enhancing CraveView's CI/CD Pipeline with Sentry and E2E Tests TL;DR: I upgraded CraveView's CI/CD pipeline by integrating Sentry for error tracking and implementing End-to-End (E2E) tests, boosting the score from 85 to 95+. This technical deep-dive explores the architecture decisions, code changes, and lessons learned. The Problem The initial problem wasn't a single error message but a series of inefficiencies in the CI/CD pipeline. The existing setup lacked comprehensive error tracking and test coverage, leading to potential issues in production. Specifically, the pipeline didn't have: Robust Error Tracking : No integrated system for capturing and analyzing errors. End-to-End Tests : Limited test coverage, which could lead to undetected issues in production. What I Tried First Initially, I focused on enhancing the test suite. I explored various testing frameworks but decided to implement E2E tests using Vitest, given its compatibility with the existing tech stack. The first approach involved setting up a basic E2E test framework. However, I encountered issues with the test environment configuration, particularly with database connectivity. The tests required a realistic database setup, which wasn't properly simulated. The Implementation Step 1: Configuring Sentry To integrate Sentry, I created configuration files for client, edge, and server initialization: sentry.client.config.ts import * as Sentry from " @sentry/nextjs " ; Sentry . init ({ dsn : " https://385038c88b6eb6ddac52d05a144ab8c1@o4511628189630464.ingest.us.sentry.io/4511629 " , // Additional config options }); sentry.edge.config.ts and sentry.server.config.ts follow a similar structure, adjusted for their respective environments. Step 2: Implementing E2E Tests I added a new test file e2e-production.test.ts in src/__tests__ : import { test , expect } from ' @playwright/test ' ; test ( ' should render the homepage ' , async ({ page }) => { await page . goto ( ' https://craveview.vercel.app ' ); await expe
AI 资讯
Upgrading CI Workflows: From Node 20 to Node 22 and Actions v5/v6
Upgrading CI Workflows: From Node 20 to Node 22 and Actions v5/v6 TL;DR: I upgraded the CI workflows for the content-automation repository from Node 20 to Node 22 and Actions v5/v6, addressing compatibility issues and improving performance. Key changes included updating upload-artifact from v5 to v7 and implementing retry with backoff. The Problem The CI workflows for the content-automation repository were using Node 20 internally, despite the configuration specifying Node 20. This discrepancy caused compatibility issues with newer versions of the GitHub Actions. Specifically, the upload-artifact action was still on version 5, which was internally targeting Node 20. What I Tried First Initially, I attempted to update the upload-artifact action to version 7, which supports Node 22. However, this change alone did not resolve the issue, as other actions like checkout and setup-python were still on older versions. The Implementation To address the compatibility issues, I updated the following actions: upload-artifact from v5 to v7 checkout to v5 setup-python to v6 Here are the specific code changes: // .github/workflows/main.yml steps: - name: Checkout code uses: actions/checkout@v5 - name: Setup Python uses: actions/setup-python@v6 - name: Upload artifact uses: actions/upload-artifact@v7 Additionally, I implemented a retry mechanism with backoff for the CI workflows: // .github/workflows/main.yml steps : - name : Retry with backoff run : | for i in {1..3}; do if ./script.sh; then break else echo "Retry $i failed, backing off..." sleep $((i * 2)) fi done Key Takeaway The key takeaway from this experience is the importance of keeping CI workflows up-to-date with the latest versions of GitHub Actions. This not only ensures compatibility but also improves performance and reliability. What's Next Next, I plan to monitor the CI workflows for any issues and continue to optimize the retry mechanism for better performance. I will also explore other ways to improve the reliabili
AI 资讯
Building VS — 2026-06-23
Here's a thinking process: Analyze User Input: Role: Ghostwriter for Roberto Luna Osorio Editorial Profile: Developer Storytelling (primary), Build in Public, Técnico, Reflexivo. Philosophy: Share the process/learnings, not just the perfect result. Mandatory narrative questions: Problem, First attempt, What went wrong, How solved, What learned, What's next. Tone: First person, direct, honest, technical but accessible, curious. Avoid corporate jargon, clickbait, marketing hype, false modesty, empty summaries. Language: Spanish (natural/colloquial tech MX/LatAm) OR English (conversational, dev-friendly). Wait, the prompt says "English only (Dev.to is primarily English)" for this specific article. I'll stick to English as instructed for the Dev.to angle. Angle: TECHNICAL DEEP-DIVE ("HOW I BUILT IT"). Focus on code, architecture, specific files. Different from Medium's narrative style. Style: Technical, precise, code-forward. Real file/function names, error messages. First person but engineer-voice. English only. Mandatory Structure: TL;DR, The Problem, What I Tried First, The Implementation, Key Takeaway, What's Next. Length: 800-1200 words. Tags: #vibecoding #buildinpublic + relevant tech tags. Input Data: Repo: VS, Date: 2026-06-23. Commits show v1.6.0 sprint 1, booking reminders, /confirm/:token, notifications, bulk actions, pipeline v2. Files modified: booking-reminders.service.ts , booking.controller.ts , email.cron.ts , notifications.controller.ts , NotificationBell.tsx , confirm/[token]/page.tsx , ventas/pipeline/page.tsx , etc. Diffs show version bumps, cron integration, notification controller refactor, new components. Constraint: Do NOT repeat angles from this week: "El control de acceso y la caja negra de las publicaciones". Choose a completely different angle. Final Instruction: Write complete article. Start directly with TL;DR. Include actual code snippets. Do NOT write a story — write a technical breakdown. Map to Editorial Profile & Constraints: Profile