# Analog: a Bun and Turborepo calendar that pins Next.js to a preview build

> Analog is an MIT TypeScript calendar monorepo built on Bun, Next.js, Drizzle on PostgreSQL and Better Auth, syncing with Google Calendar and Microsoft Graph. It is an ambitious reference stack, and `package.json` pins `next` to 16.3.0-preview.6 with no GitHub releases published, which is the honest shape of the project.

**analogdotnow/Analog** — Meet the calendar that changes everything

- Repository: https://github.com/analogdotnow/Analog
- Website: https://analog.now
- Stars: 1,592 · Forks: 181
- Language: TypeScript
- License: MIT
- Published: 2026-10-16 · Updated: 2026-10-16 · Language: en
- Canonical page: https://hysenlabs.com/projects/analogdotnow-analog

## Three containers before the app will start

The first thing to know about running Analog is that the database is not the only dependency. `docker-compose.yml` defines three services.

`analog_db` is `bitnami/postgresql:18` with a `pg_isready` healthcheck every 10 seconds, five retries, and a named volume `postgres_data` mounted at `/bitnami/postgresql`. `redis` is `redis:latest` on 6379. And `upstash-redis` is `hiett/serverless-redis-http:latest` on 8079, configured with `SRH_MODE: env`, a token and a connection string of `redis://redis:6379`.

That third service is the one that explains the design. The app talks to Upstash's HTTP Redis interface, and in local development a serverless Redis HTTP proxy sits in front of an ordinary Redis so the same client code works in both environments. `UPSTASH_REDIS_REST_URL` defaults to `http://localhost:8079` in `.env.example`.

The project is a Turborepo monorepo with `apps/`, `packages/` and `tooling/` directories, a `turbo.json`, and Bun as both runtime and package manager with `"packageManager": "bun@1.3.0"` and a `bun.lock` file.

## bun install, cp .env.example, then three OAuth consoles

The setup path is short and the environment file is where the real work is.

```bash
git clone https://github.com/analogdotnow/analog.git
cd analog
bun install
cp .env.example .env
```

Bun and Docker Desktop are the stated prerequisites. The README asks you to generate `BETTER_AUTH_SECRET` with `openssl rand -hex 32` rather than leaving the placeholder, and `.env.example` ships `DATABASE_URL` and `BETTER_AUTH_URL` with defaults already filled in.

Three integrations are documented. Google OAuth is required and needs `GOOGLE_CLIENT_ID` and `GOOGLE_CLIENT_SECRET`, the Google Calendar API enabled, and your own address added under the OAuth Audience tab as a test user. Microsoft is optional and uses Entra ID app registrations with the redirect URI `http://localhost:3000/api/auth/callback/microsoft`, then the delegated Graph permissions `Calendars.Read`, `Calendars.ReadWrite`, `User.Read` and `offline_access`. Google Maps is optional and needs `GOOGLE_MAPS_API_KEY` with the Places API (New) enabled.

The `.env.example` also carries Zoom OAuth, Vercel, Simple Analytics, a Marble CMS workspace key, and `COMPOSIO_API_KEY`, `FIRECRAWL_API_KEY` and `BROWSERBASE_API_KEY` for AI integrations, all commented as optional.

## The database script names tell you the whole data story

Four database scripts are defined, and the differences between them are the interesting part.

`db:generate` runs through Turbo without dotenv, so it can run before a database exists. `db:migrate`, `db:push` and `db:studio` all run through `dotenv --`, meaning they read your `.env` and need the connection string. `docker:up`, `docker:down` and `docker:clean` map onto `docker compose up -d`, `docker compose down` and `docker compose down -v`, the last of which removes the volumes and therefore the database.

The documented first run is `bun run docker:up` followed, once the container is healthy, by `bun run db:push`.

The persistence layer is Drizzle ORM on PostgreSQL, and the project has paired itself with Temporal. The catalog includes `temporal-polyfill`, `superjson-temporal`, `temporal-zod` and a `superjson` version, plus an effect package still on a beta. A calendar application recurring events across time zones is exactly the problem Temporal exists for, and shipping a polyfill rather than requiring a Temporal server is a reasonable call for a self-hosted app.

It also ships `trpc-to-mcp` and `trpc-to-openapi`, so the tRPC surface can be exposed to agents and as an OpenAPI document without a second definition of the API.

## The Next.js preview pin is the headline caveat

The most consequential line in `package.json` is not a dependency, it is an override:

```json
"overrides": {
  "next": "16.3.0-preview.6"
}
```

and the catalog pins `next` to the same value, with `react` and `react-dom` at `^19.2.7`.

A preview build of the framework is a defensible choice for a project whose stated purpose is demonstrating a stack, and a poor one for anything with an uptime expectation. The repository has no GitHub releases at all.

The same instinct appears elsewhere. `@typescript/native` is aliased to `npm:typescript@^7.0.2` in devDependencies while the catalog lists `typescript: ^6`, `effect` is on `4.0.0-beta.59`, and `@effect/vitest` is likewise a beta. `temporal-zod` is not taken from a registry version at all but from a build URL at pkg.pr.new pinned to a commit hash.

All of that is coherent for a project that wants to show current tooling, and all of it is a set of moving targets a team inherits on day one. Formatting is `oxfmt` over `**/*.{ts,tsx,css,md}` with a `format:check` variant, lint and type check both delegate to Turbo across packages, and the `dev`, `build`, `db:migrate`, `db:push` and `db:studio` scripts are wrapped in `dotenv --`.

## What the calendar actually does, and who it is for

Analog presents itself as an open source calendar, and the described job is synchronisation with the calendars people already use. The Google path needs the Calendar API enabled and a test user registered; the Microsoft path needs the Graph delegated permissions `Calendars.Read`, `Calendars.ReadWrite`, `User.Read` and `offline_access`.

`offline_access` is the one to notice in that list. It is what makes refresh tokens available, which is what lets a self-hosted calendar keep syncing when nobody is sitting in front of the browser. A setup that omits it produces an app that appears to work for a session and then stops syncing, which is a confusing failure to diagnose from the symptoms alone.

The stack for the front end is Next.js, TypeScript, Tailwind v4, TanStack Query and shadcn/ui, with tRPC for the typed API and the Vercel AI SDK listed among the web dependencies. Authentication is Better Auth, which is also what owns the Google and Microsoft OAuth flow and the callback route.

The audience is a developer who wants to read a complete, current, opinionated implementation of a calendar with external sync, rather than a user looking for a finished product. It is in the Vercel OSS Program, has no GitHub releases, is not archived, and the last push was on 2026-09-18. Licence is MIT.

## Conclusion

Analog fits a developer who wants a worked example of a modern calendar stack, with Temporal-based scheduling, Drizzle migrations, tRPC and a real Google Calendar and Microsoft Graph sync already wired end to end. It does not fit production deployment as it stands, because the root `package.json` pins `next` to `16.3.0-preview.6` through both an override and the catalog, and the repository has no GitHub releases. Verify first that `bun run docker:up` brings up all three compose services, that `bun run db:push` succeeds against them, and that the OAuth redirect `http://localhost:3000/api/auth/callback/microsoft` matches what you register, before you write a single calendar view.

## FAQ

### What do I need installed to run Analog locally?

Bun, as the JavaScript runtime, package manager, bundler and test runner, and Docker Desktop for the PostgreSQL database. Then clone the repository, run `bun install` and copy `.env.example` to `.env`.

### How do I set up the database for Analog?

Run `bun run docker:up`, which uses `docker-compose.yml` to start PostgreSQL, Redis and a serverless Redis HTTP proxy, then run `bun run db:push` once the database container is healthy.

### Which Microsoft Graph permissions does Analog request?

The delegated permissions `Calendars.Read`, `Calendars.ReadWrite`, `User.Read` and `offline_access`, configured in the Microsoft Entra ID app registration with the redirect URI `http://localhost:3000/api/auth/callback/microsoft`.

### Why does Analog need three Docker services?

The compose file runs `bitnami/postgresql:18` for the database, `redis:latest` on 6379, and `hiett/serverless-redis-http:latest` on 8079, which proxies the Upstash Redis HTTP interface to the local Redis so the same client code works in development.

### What ORM and database does Analog use?

Drizzle ORM with PostgreSQL, run through the `db:generate`, `db:migrate`, `db:push` and `db:studio` scripts. Redis is used alongside, accessed through the Upstash REST interface.

### Is Analog suitable for production as released?

The root `package.json` pins `next` to `16.3.0-preview.6` in both an override and the catalog, and the repository publishes no GitHub releases.

## Sources

- [analogdotnow/Analog on GitHub](https://github.com/analogdotnow/Analog)
- [Issues](https://github.com/analogdotnow/Analog/issues)
- [License: MIT](https://github.com/analogdotnow/Analog/blob/main/LICENSE)
- [Project website](https://analog.now)
- [README](https://github.com/analogdotnow/Analog/blob/main/README.md)

---

Hysen Labs editorial analysis, written from the project's own repository and release notes. Cite the canonical page: https://hysenlabs.com/projects/analogdotnow-analog
