Skip to content

Repository files navigation

NexSift

Menos ruído. Mais sinal.

NexSift is a technology intelligence product for developers. It filters, verifies and contextualizes relevant signals across AI, AWS and cloud, software development, DevOps and tech careers.

The product is designed to feel closer to a technical signal console than a traditional blog. Editorial posts are published in pt-BR. Institutional interface copy supports pt-BR, en-US and es-ES.

Screens

Home: hero and live radar Signal archive
Home: hero and live radar Signal archive with topic filters
Topic page Signal page
Topic page as a specialized radar Signal page with verified sources
About page
About the filter

Live product: https://nexsift.vercel.app - editorial feed at /blog, topic pages under /topics.

Current scope

The repository already contains the foundation for:

  • localized Next.js landing page (pt-BR as default locale without URL prefix)
  • signal-ledger blog archive
  • article pages with visible source rails
  • topic pages
  • S3 content provider (the site always reads posts from S3)
  • MiniStack local AWS simulation
  • Terraform for S3, Lambda and IAM
  • publication Lambda with Bearer authentication and Zod validation
  • local dev publish tool (direct tsx invocation)
  • RSS, sitemap, robots and Article JSON-LD
  • PostHog integration that stays disabled until a key is configured
  • GitHub Actions quality pipeline

Repository

nexsift/
├── web/             Next.js product surface
├── lambda/          publication Lambda and publishing logic
├── packages/
│   ├── schemas/     shared Zod schemas as a yarn workspace (@nexsift/schemas)
│   └── dev-publish/ local publish tool and example payloads
├── iac/
│   ├── modules/content-stack/   shared Terraform module (S3, Lambda, IAM)
│   └── environments/            local (MiniStack) and prod (AWS) stacks
├── docs/            architecture, design and editorial decisions
├── docker-compose.yml   MiniStack local environment
└── .github/         CI

See AGENTS.md before making structural or style changes.

Stack

  • Node.js 22
  • TypeScript
  • Yarn 4 workspaces with node_modules
  • Next.js
  • React
  • Tailwind CSS
  • next-intl
  • Zod
  • AWS SDK for JavaScript v3
  • AWS S3
  • AWS Lambda
  • AWS IAM
  • Terraform
  • Docker Compose
  • MiniStack
  • PostHog
  • Vercel

OpenAI API is intentionally not required for the first version.

First local run

Requirements

Install:

  • Node.js 22
  • Corepack
  • Docker
  • Terraform 1.11+

Then:

corepack enable
yarn install
cp web/.env.example web/.env.local
cp .env.example .env

Running yarn install creates yarn.lock. Commit that lockfile with the project after the first install.

Full local AWS simulation

MiniStack runs the AWS-shaped local environment. The site always reads content from S3; there is no bundled content.

1. Start MiniStack

docker compose up -d

Health check:

curl http://localhost:4566/_ministack/health

2. Build the Lambda

yarn workspace @nexsift/lambda build

3. Apply the local Terraform stack

First time only:

terraform -chdir=iac/environments/local init

Then:

terraform -chdir=iac/environments/local apply

iac/environments/local/terraform.tfvars is auto-loaded and committed. Terraform creates the local S3 bucket, IAM role and publication Lambda inside MiniStack.

4. Publish a test post

yarn tsx --env-file=.env packages/dev-publish/publish.ts --file=packages/dev-publish/payloads/example.json

The script POSTs the payload to the Lambda, which validates it with Zod, applies the editorial gates and updates the S3 indexes. The payload contract requires signalDate, signalType, depth and confidenceScore in addition to the base fields.

To wipe local content (clean slate) before republishing under a new model:

yarn tsx --env-file=.env packages/dev-publish/reset.ts

The reset script lists recent signals and deletes each one. For production endpoints it requires --allow-prod; never use it to delete test content from prod.

Check the objects in the local bucket:

curl "http://localhost:4566/nexsift-content-local?list-type=2"

5. Run the site

yarn dev

Open:

http://localhost:3000

The published post appears in the signal ledger at / and at /blog/{slug}. /pt-BR is the default locale and has no URL prefix; en-US and es-ES keep their prefix. Old /pt-BR/* URLs redirect to the unprefixed form.

Publish flow

ChatGPT Task (daily schedule)
  -> MCP connector (mcp Lambda Function URL)
  -> editorialInstructions tool (sources of truth)
  -> listRecentPosts(detail=compact) for coverage check
  -> resolvePost for exact deduplication
  -> API Gateway HTTP API
  -> Lambda: auth, Zod validation, editorial gates, source verification
  -> S3
  -> NexSift

Interactive sessions can still use the NexSift Editor GPT Action; the contract is defined in the OpenAPI spec at docs/openapi.yaml. The ChatGPT step handles research, writing and review; the Lambda only validates, verifies and publishes.

ChatGPT Tasks cannot use Custom GPTs or Actions, so the scheduled routine runs through a private MCP connector: the mcp Lambda exposes the publication contract as MCP tools and bundles the editorial docs into editorialInstructions (see docs/gpt-editor-instructions.md). Production is fronted by an API Gateway HTTP API because ChatGPT cannot reach *.lambda-url.*.on.aws domains; the Function URLs remain for local flows and rollback.

Locally, the direct publish command replaces the ChatGPT step: it reads a JSON payload from packages/dev-publish/payloads/ and invokes the Lambda through MiniStack.

Vercel MVP

Recommended Vercel setup:

  1. import the GitHub repository
  2. select web as the project root directory
  3. keep the detected Next.js framework settings
  4. set the environment variables (see below) after Vercel assigns the project URL
  5. deploy

Environment variables:

NEXT_PUBLIC_SITE_URL=https://<project>.vercel.app
NEXT_PUBLIC_POSTHOG_KEY=<project-api-key>
NEXT_PUBLIC_POSTHOG_HOST=https://us.i.posthog.com
CONTENT_BUCKET=<s3-bucket-name>
AWS_REGION=us-east-1

The site reads posts from S3, so publishing does not require a redeploy.

Future automated phase

After the product is validated, the editorial source can change without changing the web or post contract:

EventBridge Scheduler
  -> editorial Lambda
  -> source ingestion
  -> deterministic filtering
  -> OpenAI API ranking and writing
  -> review
  -> existing publishPost flow
  -> S3

The OpenAI API is therefore an optional future automation dependency, not an MVP requirement.

Content model

Posts use JSON with Markdown in content.

Core fields:

id
slug
title
description
content
whyItMatters
topics
signalDate
signalType
depth
tags
sources
relevanceScore
confidenceScore
featured
publishedAt
updatedAt
readingTime
locale

The runtime contract lives in packages/schemas and is validated by Zod.

signalDate is the date of the event. Optional draft publishedAt is the editorial publication instant: creation defaults it to now, updates preserve it when omitted, and future values are rejected. Timestamps are stored in UTC and displayed in America/Sao_Paulo.

Creation with an editorial publication instant:

{
  "post": {
    "title": "Sinal novo com contrato completo",
    "signalDate": "2026-08-18",
    "publishedAt": "2026-08-18T15:00:00.000Z"
  }
}

The remaining required creation fields are the same as packages/dev-publish/payloads/example.json. Partial update by stable identity:

{
  "post": {
    "slug": "industry-sinal-existente-2026-08-18",
    "title": "Titulo editorial corrigido",
    "publishedAt": "2026-08-18T15:00:00.000Z"
  }
}

Content storage

S3 layout:

public/
├── posts/{slug}.json
├── images/*
└── indexes/
    ├── latest.json
    └── topics/{topic}.json

private/drafts and private/runs are planned but not implemented. A database is not part of the MVP.

Product routes

/            default locale (pt-BR), no prefix
/about
/blog
/blog/{slug}
/privacy
/topics
/topics/{topic}

/en-US       same structure with prefix
/es-ES       same structure with prefix

/feed.xml
/sitemap.xml
/robots.txt
/manifest.webmanifest

Editorial content remains in pt-BR. English and Spanish users are redirected to the unprefixed blog for articles.

Open Graph image

The site has a single global OG image (1200x630) served on every page (home, blog, posts, topics). The default is generated by next/og in web/src/app/opengraph-image.tsx: dark graphite, subtle grid, signal dot and the "N/" mark, with no text.

To use your own image, drop a PNG at web/public/og.png; the route serves it automatically instead of the generated fallback.

Design and editorial references

Read:

  • docs/design.md
  • docs/editorial.md
  • docs/architecture.md
  • docs/roadmap.md

Quality commands

yarn lint
yarn typecheck
yarn build

Git conventions

Use Conventional Commits without co-author trailers.

Examples:

feat: add localized landing page
feat: add S3 content provider
fix: preserve publication timestamp on update

Licensing

Code, configuration and infrastructure in this repository are licensed under the MIT License. See LICENSE. Copyright (c) 2026 Tiago Gonçalves de Castro.

Editorial content (posts, analyses and briefings published through the NexSift pipeline) is licensed under CC BY-NC-ND 4.0: attribution to Tiago Gonçalves de Castro is mandatory, commercial use and derivatives are not allowed, and attributing authorship to third parties (including AI systems) is explicitly forbidden. See LICENSE-CONTENT.md.

If the project grows, consider registering the software (programa de computador) and the NexSift trademark at INPI, and submit the site to Google Search Console and Bing Webmaster Tools.

About

AI-assisted tech intelligence platform that filters, verifies and contextualizes relevant signals across AI, cloud, software development and tech careers.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Packages

Contributors

Languages