Open-source project
AnnaSuSu/TechSpar avatar
AnnaSuSu/TechSpar

TechSpar is an interview practice loop that writes each round back into the next

一个持续进化的面试训练系统。在线体验地址:https://techspar.cn

1,129 stars142 forksTypeScriptAGPL-3.0

At a glance

What is it?
TechSpar is a self-hosted technical interview training system in which targeted drills, resume mock interviews, job description preparation, a real-time Copilot and recording review all share one long-term profile, a knowledge base, a list of weak points and a review schedule, and every round writes its results back so the system decides what to drill next. It runs on Bun with a Hono API and a React frontend, ships an Electron desktop build, and lets each user bring their own model keys.
Who is it for?
TechSpar is worth a look if you are preparing for technical interviews and want the tool to remember what you got wrong, because the shared profile and the SM-2 review schedule are the difference between practising and revising, and the deployment model is unusually considerate with per-user keys and an optional platform fallback with quotas.
Can I use it commercially?
Yes, with strict conditions. AGPL-3.0 is a network copyleft licence: if people use a modified version over a network, for example as a hosted service, you must offer them its source code under the same licence.
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 October 22, 2026, and from our analysis. They are not legal advice.

Editorial analysis

The problem with every other interview tool

The README opens with an observation about the market. Most interview tools do the same thing, they give you a pile of questions, you answer them, and it ends. Nobody remembers which question you fell over on last time, and nobody knows what the company you are interviewing with next week actually wants to hear. TechSpar is built on the opposite premise, stated in one line, that every practice session should count, with targeted drills, resume interviews, job description preparation, the real-time Copilot and recording review sharing one long-term profile, one knowledge base, one list of weak points and one review schedule, and each round's results written back into the system to decide what the next round should be. The intended user is someone preparing for a technical interview and willing to keep a record of their own progress with a tool, which is a more demanding commitment than a question bank and the reason the memory is the point.

Five surfaces over one profile

The feature loop is a set of five surfaces, and the design point is that they share state. Targeted drill training combines the question bank, the knowledge base, the historical weak points and the mastery level to produce questions dynamically. The resume mock interview reads your resume and proceeds through a self introduction, technical questions, project deep dives and a reverse question section. Job description preparation breaks down a posting and combines it with the resume and the historical profile to generate questions relevant to that role. The real-time Copilot does speech recognition, predicts what will be asked next, suggests answers and flags risks, with optional speaker recognition by voiceprint. Recording review transcribes long or short recordings, structures them as question and answer pairs, and produces a per-question analysis with improvement suggestions. The long-term profile aggregates strengths, weak points and training history, and schedules review with SM-2.

Your own keys, or a platform key with a quota

The deployment model is unusual and worth reading the environment file for. Every model and service key, LLM, Embedding, DashScope, Tavily, Alibaba Cloud OSS and Tencent Cloud VPR, is filled in by each user after signing in, in the settings, with a two-step guide on first login, and the keys are not shared between users, each paying their own bill. The only exception is a set of optional PLATFORM_ fallbacks at the end of the environment file, which is off by default, and when it is filled in a user without their own key automatically uses the platform configuration, with the cost borne by the deployer. The comment names two typical uses, an organisation or team deployment where the admin provides one key so members do not each have to apply for an account, and internal testing where the deployer pays the model costs. The quota settings are the part to get right, with a per-user daily limit where zero or blank means unlimited, and a warning that running a platform key with no limit opens your own quota to the whole internet. The advice is to set the limit by token rather than by call count, because one real-time Copilot session can cost many times a normal question and would count as a single call otherwise.

The desktop build carries its own backend

The Electron client is the distribution most people will use, with macOS and Windows installers on the releases page, and the desktop build ships a local backend sidecar alongside the app. The build commands are separated into stages:

bash
bun run dev:desktop
bun run pack:desktop
bun run dist:desktop

More precisely, they are separated into stages, with dev:desktop running Vite, Hono and Electron together, pack:desktop producing a runnable application directory for the current platform, and dist:desktop producing the installer or archive, with per-target commands for mac-arm64 producing a DMG and a ZIP and win-x64 producing an NSIS installer, and the repository configured for macOS DMG and ZIP, Windows NSIS and Linux AppImage and DEB. A built application carries Electron and the compiled Bun backend with it, so Bun does not have to be installed to run it. The web development path is two terminals, one for the API and one for the web front end, with the front end on http://localhost:5173, and the server no longer ships a fixed default password, so the environment file needs a JWT secret, a voiceprint encryption key and a default password set to real values, and the service refuses to start with the example placeholders.

Local embeddings, and no Python anywhere in the stack

The vector search that backs the memory has a local option that removes a whole dependency. Alongside any OpenAI-compatible embeddings endpoint, the package can use Transformers.js with ONNX, by default the Xenova/bge-m3 model, which is downloaded and cached on first run and needs no Python, no PyTorch and no pip. The other services are named plainly: DashScope handles voice input, recording transcription and the real-time ASR in the Copilot, Tavily handles company information search for the Copilot, Alibaba Cloud OSS is the temporary object storage for asynchronous transcription of long recordings, and Tencent Cloud VPR is the optional voiceprint distinction between an interviewer and a candidate. The .env example also notes the privacy shape of the design, that keys are stored per user in the local data directory and that the .env file holds only startup configuration and the optional platform fallback, with a reminder that the environment file is the only place a real key appears and it must not be committed.

Data export, and a restore that will not eat your directory

The default data lives in data/, with SQLite holding the sessions and task state and the user files under data/users/{user_id}/, and the settings page offers export and import for a single account or an administrator archive of the whole site, with sensitive credentials excluded by default and only included on explicit selection. A personal backup can be imported into another account, where the data is safely rebound to the current user. The archive import validates paths, links, the tar checksum and an extraction size limit, and the vector index is treated as derived data and rebuilt after the import. The administrator system restore is described as an offline operation, and the sequence is deliberate. You put the archive outside the target data directory and run a read-only preflight, and only after the preflight passes do you stop the API, the desktop sidecar and every other process that could write to the directory, and then confirm explicitly with the confirm flag. The restore builds and validates a staging area first and then switches directories atomically, and the original data directory is kept as a sibling, timestamped data.before-system-restore-* directory rather than being deleted.

The quality gate, and a Python past

One command runs the whole gate, bun run check, which in sequence does the Bun and Node type checks, the architecture boundary check, the backend and frontend tests, the frontend TypeScript and ESLint runs, and builds for the API, the web app, the Electron main process and the compiled sidecar, and the OpenAPI file and the frontend types can be regenerated with bun run gen:api. The desktop app has three separate acceptance commands, smoke:desktop for the Electron and Hono startup chain, smoke:local-embedding which runs the compiled backend against a real ONNX local vector, and pack:desktop for a complete application directory on the current platform. The architecture boundary check is worth noting, since a project that mixes a frontend, an API, an Electron main process and a sidecar has exactly the kind of dependency direction that quietly rots, and a check for it is cheap insurance. The repository also keeps its previous generation, with legacy/python-backend as the last Python and FastAPI version, pinned at commit 73d1a7c, kept only as a historical archive and no longer receiving features, which is the practical end of the migration to the Bun and TypeScript stack.

Editorial conclusion

TechSpar is worth a look if you are preparing for technical interviews and want the tool to remember what you got wrong, because the shared profile and the SM-2 review schedule are the difference between practising and revising, and the deployment model is unusually considerate with per-user keys and an optional platform fallback with quotas. It is the wrong tool if you want a quick answer to a single question, since the setup asks for a model provider, a vector store and a data directory, and it is the wrong tool if you need a service your whole organisation shares without thinking about who pays for the model calls. Before you deploy it, read the environment example carefully, because the platform fallback key has a daily quota and a cost warning, and set the limits yourself rather than leaving them open.

Frequently asked questions

What does TechSpar do differently from a question bank?

It keeps one long-term profile, knowledge base, list of weak points and review schedule across five surfaces, targeted drills, resume mock interviews, job description preparation, a real-time Copilot and recording review, and each round writes its results back so the system decides what to drill next, with SM-2 scheduling the reviews.

How do I run TechSpar locally?

Clone the repository, install with bun install --frozen-lockfile, copy .env.example to .env and set real values for JWT_SECRET, VOICEPRINT_ENCRYPTION_KEY and DEFAULT_PASSWORD, since the service refuses the example placeholders. Then run bun run dev:api and bun run dev:web in two terminals and open http://localhost:5173, or use docker compose up --build and visit http://localhost. Bun 1.3.14 or a compatible 1.3.x is required.

Who pays for the model calls?

Each user fills in their own LLM, embedding, DashScope, Tavily, OSS and VPR keys in the settings after signing in, and those keys are not shared. The optional PLATFORM_ configuration in the environment file is the exception: when it is filled in, users without their own key fall back to it at the deployer's cost, with a per-user daily limit that should be set by token rather than by call count.

How do the desktop app and the web version differ?

The Electron build ships with its own compiled Bun backend so it does not need Bun installed, it stores the database, user files, model cache and a per-install random runtime key in the standard system application data directory, and the local Hono sidecar listens only on a dynamic port on 127.0.0.1. The web version runs the API and the front end as two processes in development, and the Docker compose file publishes the front end on port 80 with the backend behind it.

Official sources

  1. AnnaSuSu/TechSpar on GitHub
  2. License: AGPL-3.0
  3. Project website
  4. README
  5. Releases
Add this badge to your README

If you maintain this project, the badge below links readers to this analysis and shows its maintenance status from the daily GitHub snapshot. Paste the markdown into your README; add ?metric=license or ?metric=stars to the image URL for a different field.

Add this badge to your README

markdown
[![Hysen Labs](https://hysenlabs.com/badge/annasusu-techspar.svg)](https://hysenlabs.com/projects/annasusu-techspar)

Was this useful?