# self.so: Turn a LinkedIn PDF into a Personal Website with AI

> self.so is an open-source Next.js application that converts a LinkedIn profile PDF into a publishable personal website by passing it through Kimi K2.6 via the Together.ai API. It works but requires accounts at four external services before it will run locally, and several editing features are listed as future work in the README.

**Nutlope/self.so** — LinkedIn -> personal site generator

- Repository: https://github.com/Nutlope/self.so
- Website: https://www.self.so/
- Stars: 3,087 · Forks: 323
- Language: TypeScript
- License: MIT
- Published: 2026-09-24 · Updated: 2026-09-24 · Language: en
- Canonical page: https://hysenlabs.com/projects/nutlope-self-so

## What self.so Does and Who Needs Four External Services to Run It

self.so is an open-source personal website generator that takes a LinkedIn profile exported as a PDF, runs it through an AI pipeline to extract structured information, and publishes the result as a personal site at a dynamic URL. The README describes it as an open source personal site builder powered by Together.ai.

The project is not a standalone application. Running it locally requires creating accounts at four separate services: Together.ai for the language model, Upstash for the Redis database, AWS for the S3 bucket that stores uploaded PDFs, and Clerk for user authentication. Braintrust for tracing is listed as optional. Each account requires its own API key, and all keys must be filled into a .env file based on the .example.env template before the application starts. A developer who clones the repository and runs the dev command without completing those setup steps will not get a working application.

This dependency chain is not unusual for AI-powered Next.js applications, but it is worth stating plainly for anyone who expects a quick local demo.

## The PDF-to-Site Pipeline: Llama Guard, Kimi K2.6, and Structured Outputs

The README documents the four-step workflow. First, a user creates an account through Clerk authentication. Second, the uploaded PDF is stored in an AWS S3 bucket and passes a safety check using Llama Guard. Third, the PDF is sent as context to Kimi K2.6, a language model accessed via the Together.ai API, which extracts relevant information using structured outputs (JSON mode). Fourth, the extracted information is written to a dynamic route that the user can view and publish as their personal site.

The AI extraction step is the core value of the application. Rather than asking users to manually enter their experience, education, and skills into a form, self.so sends the raw PDF content to the model and receives a structured JSON response that the application then renders. The safety check with Llama Guard runs before extraction, serving as a content moderation step on the uploaded file.

The tech stack backing this pipeline is: Vercel's AI SDK as the LLM framework, @ai-sdk/togetherai as the Together.ai adapter, aws-sdk for S3 operations, @upstash/redis for the database, and @clerk/nextjs for authentication middleware. The Braintrust tracing integration is listed in the README as providing privacy-safe resume-generation tracing and observability, which can be enabled optionally for monitoring the extraction quality.

## Running self.so Locally

The README lists seven steps for cloning and running the project. After forking or cloning and creating the four required accounts, the setup requires creating a .env file with all API keys based on .example.env. Then the README instructs:

```bash
bun install
bun run dev
```

The project uses Bun as the package manager and runtime. The package.json shows that the dev script runs next dev, which starts the Next.js development server. For tests, the README documents three Vitest commands:

```bash
# Run all tests
bun run test:run

# Run tests with UI
bun run test:ui

# Run tests in watch mode
bun run test
```

The test suite uses Vitest rather than Jest, as shown in vitest.config.ts in the repository root. Test files live in the __tests__/ directory.

## External Services and Their Roles

Each of the four required services plays a distinct role in the pipeline. Together.ai hosts the Kimi K2.6 model and is the AI API provider; the Together.ai adapter is @ai-sdk/togetherai. Clerk handles user authentication, account creation, and session management through @clerk/nextjs. AWS S3 stores the uploaded PDF files; the application uses the aws-sdk package for S3 operations. Upstash Redis acts as the primary database for storing extracted profile data and site metadata, accessed through @upstash/redis.

The implication of this architecture is that the application has no local state beyond the running server process. All user data flows through external services. This suits a deployment model where the application itself is stateless and can be scaled or redeployed on Vercel without data loss, but it also means that every external service's availability affects the application. If any of the four services experiences downtime or an API key expires, the corresponding functionality stops working.

## Current Limitations and the Feature Roadmap

The README includes a public feature roadmap under "Future tasks" that identifies several unimplemented capabilities. Error logging is listed as needed to fix bugs. Returning to a preview page when a site already exists is listed as missing. Editing individual links and editing any section of the generated site are both planned but not yet implemented. Adding themes (with Ghibli mentioned as the intended first theme) is listed. Automatically deleting a previously uploaded resume when a new one is uploaded is also listed as future work.

These gaps have practical implications. A user who generates a site and then needs to correct an error in the extracted data cannot do so through the interface; the README does not document an edit flow for existing sites. If the AI extraction produces an incorrect result, the current path is to re-upload the PDF rather than to edit individual fields. The repository has published no GitHub releases, and the current version is 0.1.0 per package.json. The README also includes an AGENTS.md file in the root, which is a pattern used to instruct AI coding agents about the project, suggesting the repository is partly designed to be worked on with AI assistance.

## Comparing with JSON Resume and Maintenance State

JSON Resume is an open standard for defining a resume in a structured JSON format, with a registry of themes that render the data as HTML. It requires no AI and no external service accounts: a developer writes or exports a resume.json file, selects a theme, and renders the page locally or hosts it statically. The trade-off is that the data must be entered or converted manually; there is no automated extraction from a PDF or LinkedIn profile. self.so addresses exactly that extraction step by using a language model, at the cost of requiring Together.ai, Clerk, S3, and Upstash. For a developer who already has a well-structured resume in a machine-readable format, JSON Resume is simpler to run. For a developer who wants to generate a personal site from an existing LinkedIn profile with minimal manual data entry, self.so addresses that specific workflow.

The last push to self.so's main branch was recorded on 2026-09-04. The repository is not archived. The MIT license allows free use and redistribution, including in commercial products, without restrictions on source disclosure.

## Conclusion

self.so is useful for developers who want to build or study an AI-driven personal site generator and are comfortable wiring up four external services. Anyone looking for a simple personal site generator without AI dependencies or cloud service accounts will find the setup overhead significant. Before cloning, verify the .example.env file covers all required keys, since the application needs accounts at Together.ai, Clerk, AWS, and Upstash before the dev server returns a working result.

## FAQ

### What external accounts does self.so require to run locally?

The README lists four required accounts: Together.ai for the AI model, Upstash for the Redis database, AWS for the S3 bucket that stores uploaded PDFs, and Clerk for authentication. Braintrust for tracing is listed as optional. All required API keys go into a .env file based on the .example.env template.

### Which AI model does self.so use to extract profile information?

The README states that self.so sends the uploaded PDF as context to Kimi K2.6 via the Together.ai API, using structured outputs (JSON mode) to extract relevant information from the profile. The Llama Guard model is used for a safety check on the uploaded file before extraction.

### Can users edit their generated site after the AI extraction step?

Not yet. The README's future tasks list includes the ability to edit links and the ability to edit any section in the site as planned but unimplemented features. Currently, re-uploading a PDF is the documented path if the extracted data is incorrect.

## Sources

- [Issues](https://github.com/Nutlope/self.so/issues)
- [License: MIT](https://github.com/Nutlope/self.so/blob/main/LICENSE)
- [Nutlope/self.so on GitHub](https://github.com/Nutlope/self.so)
- [Project website](https://www.self.so/)
- [README](https://github.com/Nutlope/self.so/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/nutlope-self-so
