Model or dataset
Deodat-Lawson/LaunchStack avatar
Deodat-Lawson/LaunchStack

LaunchStack: a TypeScript engine for document ingestion, RAG and knowledge graphs

AI-powered StartUp Accelerator Engine built with Next.js, LangChain, PostgreSQL + pgvector. Upload, organize, and chat with documents. Includes predictive missing-document detection, role-based workflows, and page-level insight extraction.

887 stars124 forksTypeScriptApache-2.0

At a glance

What is it?
LaunchStack is a pnpm workspace that ships an engine (protocol, evidence, application, adapters, core) plus a Next.js reference app for uploading, organising and chatting with documents. The engine packages are not on npm yet, so adoption today means running this repository.
Who is it for?
Adopt LaunchStack if you want a self-hosted, ports-and-adapters TypeScript engine you can read end to end, and you are willing to run the repository rather than install a published package. Do not adopt it if you need a supported npm dependency with a stable public API, or if you cannot operate Postgres with pgvector and run a separate worker process.
Can I use it commercially?
Yes. Apache-2.0 is a permissive licence: you can use, modify and sell software built on it, as long as you keep its copyright and licence notices.
Is it still maintained?
Yes. The repository last received commits 5 days ago.
What is it written in?
Mainly TypeScript, according to GitHub's language statistics.

Answers come from the project's GitHub data, last synced on September 15, 2026, and from our analysis. They are not legal advice.

DEEP OPEN-SOURCE ANALYSIS

The gap LaunchStack tries to fill in a Next.js AI stack

Most TypeScript RAG examples stop at a vector store and a chat route. LaunchStack's README describes something broader: a ports-based engine covering ingestion, OCR, a knowledge graph, LLM abstractions and background jobs, wired into a reference application that shows how the pieces fit together. The intended audience is a team building an AI-native product in TypeScript that has already decided it needs document ingestion and retrieval, and wants the surrounding machinery (durable jobs, role-based workflows, page-level insight extraction) rather than a single embedding call. The repository also carries startup-flavoured framing in its description, including predictive missing-document detection, but the README's own framing is the more useful one: this is an engine plus a demo app, not a hosted product. The distinction matters because the engine packages are explicitly not yet on npm, so the only way to use them today is to run the repository.

Ports, adapters and where ingestion actually executes

The architecture named in the README is ports-based, with engine packages split as @launchstack/protocol, evidence, application and adapters, plus a core facade. That split is the interesting design decision: the protocol package presumably holds the interfaces, application holds the use cases, and adapters hold the concrete bindings to Postgres, pgvector and whatever LLM you point it at. The core facade is what an embedding consumer imports. The runtime split is sharper still. apps/web is described as UI, auth, command acceptance and synchronous reads. apps/worker is the durable workflow coordinator, and the README is blunt that ingestion runs there, not in web. The practical consequence is stated plainly: web dev is plain next dev, it accepts uploads but processes nothing, and documents will sit queued forever unless the worker runs alongside it. That command-and-worker shape is a deliberate trade. It buys durability and lets the web process stay responsive, and it costs you a second process to operate and monitor.

Getting it running with pnpm and Docker

Requirements are Node 20 or newer and pnpm 10.15.1, which corepack enable will pick up from the pinned version. The clone, install and env copy are the usual three commands: git clone the repository, cd LaunchStack, pnpm install, then cp .env.example .env. apps/web/src/env.ts refuses to boot without DATABASE_URL and BETTER_AUTH_SECRET, and the README suggests generating the secret with openssl rand -base64 32. The Docker path is the recommended one and is driven by make targets: make up-prod for a lite stack in detached mode at roughly 400MB RAM, make up-ocr to add Docling for Office documents at roughly 1.2GB RAM, make logs, make down to keep volumes, and make down-clean to wipe them. make up exists but runs in the foreground, so you need a second shell to stop it. Windows users without make get the equivalent docker compose invocations with --env-file .env and the ocr profile. Without Docker you need Postgres with the pgvector extension available, because the migration runner enables it and exits non-zero on stock Postgres. Then four commands: db:migrate from @launchstack/web, an optional db:seed from @launchstack/core, dev from @launchstack/web on port 3000, and dev from @launchstack/worker on port 8020. The Inngest dev UI on 8288 is optional and only needed for the Inngest-hosted background verticals, not for ingestion.

Chat configuration is a base URL, not a vendor key

This is the part most likely to trip up a first run. Chat needs no variable at all: with CHAT_BASE_URL unset it defaults to Google Gemini's OpenAI-compatible endpoint, authenticated with GOOGLE_AI_API_KEY. To reach anything else you set CHAT_BASE_URL plus CHAT_API_KEY. The README is emphatic that a bare OPENAI_API_KEY, OPENROUTER_API_KEY or OLLAMA_BASE_URL will not configure chat, and that none of them is forwarded to the Gemini default. The reasoning given is that a key names who you are, not where the request goes, and that those providers all speak the same OpenAI chat-completions protocol, so each is reached through CHAT_BASE_URL like any other. Only AI_BASE_URL and AI_API_KEY, a straight rename of the canonical pair, are still translated, and that comes with a deprecation warning. I think this is the right call for a ports-based engine, because it collapses N vendor integrations into one configuration surface. It is also a real migration hazard: anyone arriving with an OPENAI_API_KEY in their environment and expecting it to work will get the Gemini default instead, and the failure will look like a provider problem rather than a config one.

Self-hosting defaults and the first-signup owner

A deployment is self-hosted unless DEPLOYMENT_MODE is set to cloud, and the defaults are chosen for that case. Usage is recorded but never gated. No telemetry is loaded. No assets are fetched from a CDN. The instance identifies itself by the host you serve it from. There is no separate admin bootstrap: the first person to sign up becomes the owner of the workspace they create, already verified. That is convenient for a single-tenant install and awkward for anything exposed to the public internet before you have claimed the workspace. Two further details are worth internalising. The marketing site at launchstack.app is a separate app in apps/landing that Docker and Compose do not build, so on your own instance the root path is the sign-in page, not a pitch. And the repository root is not an application: it is a pnpm workspace with no runtime dependencies and no server, pnpm dev at the root fails with ERR_PNPM_NO_SCRIPT, and only repo-wide commands such as lint, typecheck, check and the Changesets scripts live there. Always target a package with --filter.

The npm gap is the main adoption risk

The engine packages are not yet on npm. The README states that the first release will publish them together through the Changesets flow in release.yml, and that a hardcoded-repo gate and a missing .changeset directory previously blocked releases. The workflow is said to validate the packed tarball with publint and a Node-ESM loadability check for every subpath. Until that release lands, consuming the engine means running this repository. That is the honest limitation to weigh. There is no published version to pin, no semver contract to depend on, and no way to take the engine as a library without vendoring or forking. The migration story compounds it: db:migrate from @launchstack/web applies both migration sets, engine then product, while running it from @launchstack/core applies only the engine set, which the README says is what a consumer embedding the engine uses rather than what a full app needs. Nothing else creates schema. If you plan to embed the engine, you are adopting a migration boundary as well as a code boundary, and getting that wrong means missing tables rather than a clear error.

Where a plain RAG pipeline is the better choice

The obvious alternative is assembling the same capability from a vector store plus a framework such as LangChain, which this project also lists among its topics. The difference in approach is structural. A hand-rolled pipeline is typically a single process: the API route embeds and stores, and the request completes when the write does. LaunchStack separates command acceptance from execution and puts ingestion in a durable worker. If your ingestion is small, synchronous and low-stakes, that separation is overhead you will pay for in operational surface: a second process, a port, and a queue you have to watch. The same applies to the knowledge graph. If your retrieval needs are satisfied by pgvector similarity search over chunks, the graph layer is additional schema and additional moving parts for a capability you are not using. LaunchStack earns its complexity when documents are large or arrive in bursts, when OCR of Office files matters (which is why make up-ocr pulls in Docling), and when you need ingestion to survive a web process restart. Below that threshold, a smaller stack is easier to reason about.

Maintenance cost and the Apache-2.0 boundary

Two ongoing costs are visible in the material. The first is operational: a Postgres instance with pgvector, a web process, and a worker on port 8020 that must stay up, plus optionally the Inngest dev server on 8288 for the background verticals. The README notes that make down keeps volumes so database and S3 data persist, which means state accumulates across restarts and make down-clean is the reset. The second is the release cadence. The only listed release is v1.0.0, tagged as the Final PDR AI Release, and the engine packages have not shipped to npm at all, so upgrade paths are not yet demonstrated. On licensing, the repository is Apache-2.0 and the README displays the badge accordingly. That is a permissive licence, but it says nothing about the dependencies you will pull in through pnpm install, and it says nothing about the separate apps/landing site, which is not part of any self-hosted deployment. Read the licence file and audit the dependency tree rather than treating the badge as the whole answer. Nothing here is legal advice.

Editorial conclusion

Adopt LaunchStack if you want a self-hosted, ports-and-adapters TypeScript engine you can read end to end, and you are willing to run the repository rather than install a published package. Do not adopt it if you need a supported npm dependency with a stable public API, or if you cannot operate Postgres with pgvector and run a separate worker process. Before committing, verify three things: that pgvector is available in your Postgres, that you can run both db:migrate sets from @launchstack/web rather than only the engine set from @launchstack/core, and that the worker on port 8020 stays up alongside web, because uploads accepted by next dev alone are never processed.

Official sources

  1. Deodat-Lawson/LaunchStack on GitHub
  2. Issues
  3. License: Apache-2.0
  4. README
  5. Releases
Community notes

Community notes