Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 25 additions & 21 deletions .env.example
Original file line number Diff line number Diff line change
@@ -1,31 +1,35 @@
# Copy this file to .env.local for local work. Platform-provided variables and
# compatibility aliases are intentionally omitted.

# Supabase transaction-pooler URL at runtime and a direct or session-pooler URL
# for migrations and cron configuration.
# Copy to .env.local. All values are intentionally blank; basic dev/build needs none.
# Database: runtime pooler URL, and optional direct/session URL for operations.
DATABASE_URL=
DATABASE_URL_UNPOOLED=

# Optional fallback for public repository discovery and pinned GitHub embeds.
# GitHub activity: JSON object mapping configured logins to personal access tokens.
# Public authors and IDs live in src/content/site.ts. Keep tokens only in this environment.
GITHUB_TOKENS=
# Optional public repository/embed access; GH_TOKEN is the GitHub CLI alias.
GITHUB_TOKEN=
GH_TOKEN=

# Account-specific tokens used to read each authenticated user event feed and
# repository commits, including private repositories the account can access.
GITHUB_F0RR0_TOKEN=
GITHUB_YUPPIESTECHDEV_TOKEN=

# Authenticates Supabase Cron requests.
# Use at least 32 random characters.
# Independent secrets, each at least 32 random characters.
CRON_SECRET=

# Signs activity pagination cursors independently of cron authentication.
# Use at least 32 random characters.
GITHUB_ACTIVITY_CURSOR_SECRET=

# Verifies GitHub webhook signatures. Use at least 32 random characters and
# configure the same value on the webhook sender.
GITHUB_WEBHOOK_SECRET=

# Optional. Generates outcome summaries for public work units. Missing
# credentials, exhausted budgets, and provider failures remain facts-only.
# Optional outcome summaries (activity works without this).
OPENAI_API_KEY=
# Optional public PostHog capture key and region (us or eu; defaults to us).
NEXT_PUBLIC_POSTHOG_KEY=
NEXT_PUBLIC_POSTHOG_REGION=

# Optional local server port and public fallback port (default 3000).
PORT=
NEXT_PUBLIC_PORT=

# Supplied by Next/Vercel. Leave blank locally; do not manage a separate site URL.
NODE_ENV=
VERCEL=
VERCEL_ENV=
VERCEL_PROJECT_PRODUCTION_URL=
VERCEL_URL=
# Vercel also supplies NEXT_PUBLIC_VERCEL_ENV and NEXT_PUBLIC_VERCEL_PROJECT_PRODUCTION_URL at build time.
# Codex account credentials belong in Supabase Vault; see docs/codex-stats.md.
11 changes: 3 additions & 8 deletions .github/workflows/github-activity-backfill.yml
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,8 @@ on:
account:
description: Account whose token and accessible repositories are scanned
required: true
default: f0rr0
type: choice
options:
- f0rr0
- yuppiestechdev
- all
default: all
type: string
repository_id:
description: Numeric repository ID; blank scans repositories active in the window
required: false
Expand Down Expand Up @@ -57,8 +53,7 @@ jobs:
ACCOUNT: ${{ inputs.account }}
DATABASE_URL: ${{ secrets.ACTIVITY_DATABASE_URL }}
END_DATE: ${{ inputs.end_date }}
GITHUB_F0RR0_TOKEN: ${{ secrets.ACTIVITY_F0RR0_TOKEN }}
GITHUB_YUPPIESTECHDEV_TOKEN: ${{ secrets.ACTIVITY_YUPPIESTECHDEV_TOKEN }}
GITHUB_TOKENS: ${{ secrets.ACTIVITY_GITHUB_TOKENS }}
MAXIMUM_MINUTES: ${{ inputs.maximum_minutes }}
REPOSITORY_ID: ${{ inputs.repository_id }}
START_DATE: ${{ inputs.start_date }}
Expand Down
3 changes: 3 additions & 0 deletions .github/workflows/validate.yml
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,9 @@ name: validate
on:
pull_request:

permissions:
contents: read

jobs:
validate:
name: validate
Expand Down
3 changes: 2 additions & 1 deletion .worktreeinclude
Original file line number Diff line number Diff line change
@@ -1,2 +1,3 @@
# Copy the complete local runtime configuration into Codex-managed worktrees.
# Copy development-only local configuration into managed worktrees.
# Keep production credentials in deployment secret storage, not .env.local.
.env.local
2 changes: 1 addition & 1 deletion BLOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ prompts, and desktop/mobile/social crops. Keep research reports, per-post image
prompts and production briefs transient; do not commit them to the repository.
Reserve `docs/` for current implementation and usage documentation.

Public identity URLs always use `https://f0rr0.dev`; preview deployments return
Public identity URLs use Vercel’s `VERCEL_PROJECT_PRODUCTION_URL`; preview deployments return
`noindex`. The sitemap lists intended search destinations, while alternate
Markdown and profile exports remain discoverable through links and `llms.txt`.

Expand Down
86 changes: 80 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,13 @@ bun run dev
```

The website works without secrets; the persisted commit feed stays empty until
Postgres is configured. See [the commit sync guide](docs/github-commits.md) for
database, Supabase Cron, account polling, and webhook setup.
PostgreSQL is configured. Set `DATABASE_URL` for application queries and, when
using a runtime transaction pooler, `DATABASE_URL_UNPOOLED` to a direct or
session-pooler connection for migrations and cron setup. Supply these in
`.env.local` for local use and in Vercel environment settings for deployments;
the application does not provision a database or synchronize connection settings.
See [the commit sync guide](docs/github-commits.md) for Supabase Cron, account
polling, and webhook setup.
The separate [Codex stats guide](docs/codex-stats.md) covers its encrypted
account snapshots and scheduled sync.

Expand All @@ -28,10 +33,79 @@ bun test
bun run build
```

Vercel production builds apply pending migrations before building the site,
using the database connection already synchronized by Supabase. Preview and
local builds skip migrations. Apply them manually in other environments with:
`bun run build` only builds the application. To use the existing production
migrations and Supabase scheduling, set Vercel's **Build Command** to:

```sh
bun run db:migrate
bun scripts/migrate-production-database.ts && bun run build && bun scripts/configure-supabase-cron.ts --production-build
```

Those operational scripts act only on Vercel production deployments. The
migration runs before the build because pages may read the database while
building. Cron configuration follows a successful build; it is not a
post-deployment hook. Local operations remain `bun run db:migrate` and
`bun run supabase:cron`.

## Updating an existing deployment

Move the existing per-account token values into one `GITHUB_TOKENS` JSON object,
keyed by the logins in `src/content/site.ts`. The same tokens can be reused; no
new tokens or account IDs are required. Set this variable in Vercel and set the
`ACTIVITY_GITHUB_TOKENS` repository secret for the manual backfill Action (GitHub
reserves secret names beginning with `GITHUB_`). Keep the old token
variables until the new deployment has been verified, then remove them.

Keep the existing database, webhook, cron, cursor-signing and OpenAI credentials.
To retain analytics, set `NEXT_PUBLIC_POSTHOG_KEY` to the existing project's public
capture key; `NEXT_PUBLIC_POSTHOG_REGION` defaults to `us`.

For the database-backed installation, set the Build Command above before deploying
this change. It applies migration `0022`, builds against the updated schema, then
updates cron configuration. Migration `0022` only replaces seven username
allowlists with valid-login checks; it adds no tables or columns and rewrites no
stored history. Leave older applied migrations intact.

## Customize once

- `src/content/resume.ts`: identity, social profiles, career, education and PDF paths.
- `src/content/home.ts`: introduction and featured work.
- `src/content/site.ts`: tracked GitHub authors, language and work-log timezone.
- `.env.example`: every supported environment variable, with blank values.

Vercel's `VERCEL_PROJECT_PRODUCTION_URL` supplies the canonical domain, including
for preview metadata. Enable **Automatically expose System Environment Variables**
in the project settings. Local URLs use localhost and the configured port.
There is no separately maintained site URL or blog asset base URL: exported
Markdown uses the image URLs already emitted by the MDX compiler.

GitHub activity uses configured public authors and separate credentials. See the
[GitHub activity guide](docs/github-commits.md) for token format and service setup,
and the [analytics guide](docs/analytics.md) for optional PostHog configuration.

Each installation needs its own database. Cron/Vault names are installation-wide;
sharing one database between independent sites is unsupported. Set `vercel.json`
regions to match your database location (the existing deployment uses Tokyo).
Personal content and the authoring defaults under `.rulesync/` can remain or be
edited independently of the application configuration.

`.worktreeinclude` automatically copies `.env.local` into local worktrees. Use
only development-scoped credentials there; keep production credentials in the
deployment secret store. The copied file remains ignored by Git.

Docker is required for PostgreSQL integration tests; Bun reports those tests as
skipped when Docker is unavailable. Typst tooling is needed to regenerate the
résumé PDF. Versions are pinned in `mise.toml`, `package.json` and `bun.lock`;
CI installs with the frozen lockfile.

GitHub native secret scanning and push protection are enabled for this repository.
Enable those repository settings when creating a fork. The historical Firebase
project configuration still needs an owner-side restrictions/retirement review.
Report credential exposure privately through GitHub's security reporting feature
when enabled. Otherwise, use the maintainer contact in `src/content/resume.ts`;
never paste credentials into a public issue.

## Reuse status

A code license and the reuse policy for personal writing/images still need to be
chosen. Public source availability alone is not a grant of reuse rights. Preserve
upstream copyright/license notices for vendored fonts, assets and authoring skills.
88 changes: 43 additions & 45 deletions bun.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions bunfig.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[install]
exact = true

[test]
preload = ["./tests/setup.ts"]
4 changes: 2 additions & 2 deletions docs/analytics.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,8 @@ The site uses PostHog US Cloud for pageviews, acquisition attribution, and expli

## Configuration

- `src/instrumentation-client.ts` initializes the SDK only in production on `f0rr0.dev`. The public project token and API path are configured in source; no PostHog environment variables are needed.
- `src/proxy.ts` forwards `/_r7k2/*` to fixed US ingestion and asset hosts. It strips Cookie, Authorization, and Referer headers. Collector trailing slashes are preserved; ordinary page trailing slashes receive a 308 redirect.
- `src/instrumentation-client.ts` initializes the SDK only on the canonical production host when `NEXT_PUBLIC_POSTHOG_KEY` is configured. `NEXT_PUBLIC_POSTHOG_REGION` selects `us` (default) or `eu` for both the SDK and proxy; preview and local deployments do not capture events.
- `src/proxy.ts` forwards `/_r7k2/*` to the selected region’s ingestion and asset hosts. It strips Cookie, Authorization, and Referer headers. Collector trailing slashes are preserved; ordinary page trailing slashes receive a 308 redirect.
- The SDK uses always-cookieless mode, memory persistence, and no person profiles. Autocapture, replay, surveys, heatmaps, automatic exceptions, performance collection, and feature flags are disabled.
- Do Not Track and Global Privacy Control signals do not change capture behavior.
- `src/lib/analytics.ts` contains the typed event contract, link classification, and property redaction. URL queries and fragments, referrer paths, ad click IDs, and search terms are removed. Campaign values must be short public slugs.
Expand Down
Loading