Skip to content

feat(docs): add initial documentation structure and resources#68

Closed
JoachimLK wants to merge 1 commit into
mainfrom
feat/documentation-docus
Closed

feat(docs): add initial documentation structure and resources#68
JoachimLK wants to merge 1 commit into
mainfrom
feat/documentation-docus

Conversation

@JoachimLK
Copy link
Copy Markdown
Contributor

@JoachimLK JoachimLK commented Mar 5, 2026

  • Created package.json for documentation project setup with Nuxt.
  • Added logo assets for dark and light themes.
  • Implemented architecture, changelog, and roadmap resources for documentation.
  • Configured TypeScript support with tsconfig.json extending Nuxt's configuration.

Summary

  • What does this PR change?
  • Why is this needed?

Type of change

  • Bug fix
  • Feature
  • Refactor
  • Docs
  • Chore

Validation

  • I tested locally
  • I added/updated relevant documentation
  • I verified multi-tenant scoping and auth behavior for affected API paths

DCO

  • All commits in this PR are signed off (Signed-off-by) via git commit -s

Summary by CodeRabbit

  • New Features

    • Added "Docs" link in navigation pointing to official documentation site.
  • Documentation

    • Launched comprehensive official documentation site covering getting started, system requirements, configuration, architecture, features (job management, candidate pipeline, public job board, dashboard), deployment guides, API reference, and contribution guidelines.
    • Added multilingual support for documentation navigation label.

- Created package.json for documentation project setup with Nuxt.
- Added logo assets for dark and light themes.
- Implemented architecture, changelog, and roadmap resources for documentation.
- Configured TypeScript support with tsconfig.json extending Nuxt's configuration.
@railway-app railway-app Bot temporarily deployed to applirank / reqcore-pr-68 March 5, 2026 10:31 Destroyed
@railway-app
Copy link
Copy Markdown

railway-app Bot commented Mar 5, 2026

🚅 Deployed to the reqcore-pr-68 environment in applirank

Service Status Web Updated (UTC)
applirank ✅ Success (View Logs) Mar 5, 2026 at 10:35 am

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 5, 2026

📝 Walkthrough

Walkthrough

This pull request introduces a comprehensive documentation site for Reqcore with extensive guides on getting started, configuration, architecture, features, deployment, and API. It adds runtime configuration for documentation URL, navigation links with multi-language support, and a Nuxt-based docs application with MCP resource definitions.

Changes

Cohort / File(s) Summary
Configuration & Environment
.env.example, nuxt.config.ts, docs/nuxt.config.ts
Added public docsUrl runtime configuration (defaulting to https://docs.reqcore.com) and documented via commented env variables; Docus-based Nuxt config for docs site with SEO metadata, site settings, and LLM/MCP integration.
Navigation & UI Updates
app/pages/index.vue, README.md
Added runtime-config-driven docs link in header navigation with label from i18n; updated Live Demo link target from ARCHITECTURE.md to external docs site.
Internationalization
i18n/locales/{en.json, de.json, fr.json, nb.json, vi.json}
Added "docs" navigation label across English, German, French, Norwegian Bokmål, and Vietnamese locale files (5 translations).
Documentation Site Infrastructure
docs/package.json, docs/tsconfig.json, docs/app/app.config.ts, docs/.gitignore
Established Nuxt 4 docs package with dependencies (docus, nuxt, better-sqlite3), TypeScript config, centralized app configuration with SEO, header branding, socials, GitHub settings, TOC, UI colors, assistant FAQs, and locale config; standard gitignore patterns.
Documentation Content — Getting Started
docs/content/docs/1.getting-started/{1.introduction.md, 2.quick-start.md, 3.system-requirements.md, 4.project-structure.md}
Comprehensive guides on Reqcore's purpose (open-source ATS), quick Docker-based setup, hardware/software prerequisites, and full project directory structure with explanation.
Documentation Content — Configuration
docs/content/docs/2.configuration/{1.environment-variables.md, 2.database.md, 3.storage.md, 4.authentication.md}
Documentation on all env vars with Zod validation, PostgreSQL + Drizzle ORM setup with multi-tenancy, S3-compatible object storage (MinIO/AWS), and Better Auth + organization-based multi-tenancy architecture.
Documentation Content — Architecture
docs/content/docs/3.architecture/{1.overview.md, 2.data-model.md, 3.security.md}
System design overview (monolithic Nuxt 4 with server/database/storage), entity-relationship model with candidate/job/application flows, and comprehensive security coverage (auth, authorization, validation, rate limiting, document security, headers).
Documentation Content — Features & API
docs/content/docs/4.features/{1.job-management.md, 2.candidate-pipeline.md, 3.public-job-board.md, 4.dashboard.md}, docs/content/docs/6.api/1.overview.md
Job lifecycle and publishing, candidate pipeline with Kanban/table views and deduplication, public job board with SEO/ISR/rate limiting, recruiter dashboard with stat cards and navigation, and REST API overview with authentication, error handling, and per-resource endpoints.
Documentation Content — Deployment
docs/content/docs/5.deployment/{1.self-hosting.md, 2.railway.md, 3.docker.md}
Self-hosted production setup with Caddy/systemd, Railway platform deployment with services, and Docker Compose usage for development/production with health checks.
Documentation Content — Contributing & FAQ
docs/content/docs/7.contributing/{1.development-setup.md, 2.internationalization.md}, docs/content/docs/8.faq.md, docs/content/index.md
Contributor onboarding with prerequisites, scripts, and DCO sign-off; i18n setup with Crowdin integration across 6 languages; FAQ covering general, self-hosting, features, and technical questions; and docs landing page with hero and card-based navigation.
MCP Resource Definitions
docs/server/mcp/resources/{architecture.ts, changelog.ts, roadmap.ts}
Three MCP resources exposing ARCHITECTURE.md, CHANGELOG.md, and ROADMAP.md with descriptions for AI-ready content integration.

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

Poem

🐰 Hops through docs with glee,
A knowledge tree now for all to see,
From quick starts to deployment's gleam,
Reqcore's story, a developer's dream!
Configuration, guides, and FAQs so bright—
Your open-source ATS shines in the light!

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 inconclusive)

Check name Status Explanation Resolution
Description check ❓ Inconclusive The description is incomplete; it lists what was done but lacks detailed explanations of why these changes are needed and does not fully address the template sections. Expand the 'Summary' section to explain the motivation and impact. Complete the 'Type of change' by selecting appropriate checkboxes, and indicate completion status for validation items and DCO sign-off.
✅ Passed checks (2 passed)
Check name Status Explanation
Title check ✅ Passed The title accurately describes the main change: adding initial documentation structure and resources using a feature prefix.
Docstring Coverage ✅ Passed No functions found in the changed files to evaluate docstring coverage. Skipping docstring coverage check.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.

✨ Finishing Touches
  • 📝 Generate docstrings (stacked PR)
  • 📝 Generate docstrings (commit on current branch)
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Post copyable unit tests in a comment
  • Commit unit tests in branch feat/documentation-docus

Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out.

❤️ Share

Comment @coderabbitai help to get the list of available commands and usage tips.

Copy link
Copy Markdown

@coderabbitai coderabbitai Bot left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 7

Note

Due to the large number of review comments, Critical, Major severity comments were prioritized as inline comments.

🟡 Minor comments (18)
docs/content/docs/4.features/1.job-management.md-12-14 (1)

12-14: ⚠️ Potential issue | 🟡 Minor

Add language specifier to fenced code block.

Static analysis flagged that the code block lacks a language specifier. For ASCII diagrams, use text or plaintext.

📝 Suggested fix
-```
+```text
 draft → open → closed → archived
 ```
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/content/docs/4.features/1.job-management.md` around lines 12 - 14,
Update the fenced code block containing the ASCII diagram "draft → open → closed
→ archived" to include a language specifier (e.g., text or plaintext) so static
analysis recognizes it as plain text; locate the block with those exact contents
and change the opening fence from ``` to ```text.
docs/content/docs/5.deployment/2.railway.md-57-58 (1)

57-58: ⚠️ Potential issue | 🟡 Minor

Start command and pre-deploy step don't match railway.json.

The documentation states the start command is node .output/server/index.mjs, but railway.json specifies:

  • startCommand: npm run start
  • preDeployCommand: npm run db:migrate && npm run db:seed

The pre-deploy step (database migrations and seeding) is not documented, which users need to understand for proper deployment.

📝 Suggested fix
 Build command: `npm run build` (auto-detected from `package.json`)
-Start command: `node .output/server/index.mjs`
+Start command: `npm run start` (configured in `railway.json`)
+
+Railway runs database migrations and seeding automatically before starting via `preDeployCommand`.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/content/docs/5.deployment/2.railway.md` around lines 57 - 58, The docs
currently list the start command and omit pre-deploy steps that differ from
railway.json; update the documentation to match railway.json by changing the
start command from "node .output/server/index.mjs" to "npm run start", keep the
build command as "npm run build", and add a note documenting the pre-deploy
step: run "npm run db:migrate && npm run db:seed" (referencing railway.json keys
startCommand and preDeployCommand) so users know to run migrations and seed data
before deployment.
docs/content/docs/5.deployment/1.self-hosting.md-129-135 (1)

129-135: ⚠️ Potential issue | 🟡 Minor

Backup commands use hardcoded credentials that may not match user configuration.

The commands use -U reqcore reqcore but docker-compose.yml uses ${DB_USER} and ${DB_NAME} from .env. Users with different credentials will need to adjust these commands.

📝 Suggested fix
 ### Database

 ```bash
 # Backup
-docker compose exec db pg_dump -U reqcore reqcore > backup_$(date +%Y%m%d).sql
+docker compose exec db pg_dump -U $DB_USER $DB_NAME > backup_$(date +%Y%m%d).sql

 # Restore
-docker compose exec -i db psql -U reqcore reqcore < backup_20260101.sql
+docker compose exec -i db psql -U $DB_USER $DB_NAME < backup_20260101.sql
 ```
+
+Replace `$DB_USER` and `$DB_NAME` with the values from your `.env` file, or source it first with `source .env`.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/content/docs/5.deployment/1.self-hosting.md` around lines 129 - 135,
Replace the hardcoded database user/name in the example backup/restore commands
so they use the environment variables used in docker-compose; update the pg_dump
and psql invocations (the lines calling pg_dump and psql) to use $DB_USER and
$DB_NAME instead of the literal "reqcore", and mention sourcing the .env (e.g.,
source .env) or replacing those variables with your actual values so the
commands match the ${DB_USER}/${DB_NAME} settings from docker-compose.
docs/content/docs/5.deployment/1.self-hosting.md-145-146 (1)

145-146: ⚠️ Potential issue | 🟡 Minor

MinIO credentials are hardcoded as defaults.

The example uses minioadmin minioadmin but docker-compose.yml configures MinIO with ${STORAGE_USER} and ${STORAGE_PASSWORD} from .env. Add a note that users should substitute their actual credentials.

📝 Suggested fix
 # Configure
-mc alias set local http://localhost:9000 minioadmin minioadmin
+mc alias set local http://localhost:9000 $STORAGE_USER $STORAGE_PASSWORD
 ```
+
+Replace `$STORAGE_USER` and `$STORAGE_PASSWORD` with the values from your `.env` file.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/content/docs/5.deployment/1.self-hosting.md` around lines 145 - 146, The
example command hardcodes MinIO credentials (mc alias set local
http://localhost:9000 minioadmin minioadmin); update the documentation to tell
users to replace the hardcoded minioadmin/minioadmin with their actual
credentials by referencing the environment variables used in docker-compose:
$STORAGE_USER and $STORAGE_PASSWORD (e.g., "replace $STORAGE_USER and
$STORAGE_PASSWORD with the values from your .env file"). Ensure the note appears
immediately after the shown mc alias set line so readers know to substitute
their own credentials.
docs/content/docs/5.deployment/3.docker.md-54-66 (1)

54-66: ⚠️ Potential issue | 🟡 Minor

Documentation describes 3 Dockerfile stages, but actual Dockerfile has only 2.

The documentation claims a three-stage build (Dependencies → Build → Runtime), but the actual Dockerfile uses only two stages:

  • Stage 1 "builder": Installs dependencies AND runs the build
  • Stage 2 "runner": Runtime

This should be corrected to match the actual implementation.

📝 Suggested fix
 ## Dockerfile (Production)

-The `Dockerfile` uses a multi-stage build for minimal production images:
+The `Dockerfile` uses a two-stage build for minimal production images:

-### Stage 1: Dependencies
+### Stage 1: Build

-Installs Node.js dependencies from `package.json`.
-
-### Stage 2: Build
-
-Runs `nuxt build` to generate the production server in `.output/`.
+Installs Node.js dependencies and runs `nuxt build` to generate the production server in `.output/`.

-### Stage 3: Runtime
+### Stage 2: Runtime

 Copies only the built output and runs with `node .output/server/index.mjs`. The final image is minimal — no source code, no dev dependencies.
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/content/docs/5.deployment/3.docker.md` around lines 54 - 66, Update the
docs to reflect the actual Dockerfile multi-stage setup: change the description
from three stages to two, naming them "builder" (which installs dependencies and
runs nuxt build producing .output/) and "runner" (which copies .output and runs
node .output/server/index.mjs); remove or reword the separate "Dependencies"
stage and ensure text accurately states that the builder performs both install
and build steps so the documentation matches the Dockerfile.
docs/content/docs/3.architecture/1.overview.md-12-12 (1)

12-12: ⚠️ Potential issue | 🟡 Minor

Add language identifiers to fenced code blocks (markdownlint MD040).

Line 12, Line 51, Line 87, Line 93, Line 99, and Line 105 use unlabeled fenced blocks. Please set an explicit language (e.g., text) to satisfy linting and keep formatting consistent.

Suggested fix
-```
+```text
 ...
-```
+```

-```
+```text
 Request → Auth Guard → Extract orgId from session → Scope all queries by orgId
-```
+```

-```
+```text
 Browser → Cookie → Nitro → requireAuth() → Extract orgId → DB Query (scoped by orgId) → JSON Response
-```
+```

-```
+```text
 Browser → Nitro → DB Query (WHERE status = 'open') → JSON Response
-```
+```

-```
+```text
 Browser → multipart/form-data → Nitro → Validate MIME → Sanitize filename → Upload to S3 → Store metadata in DB
-```
+```

-```
+```text
 Browser → Authenticated request → Nitro → Fetch from S3 → Stream bytes → Browser receives file
-```
+```

Also applies to: 51-51, 87-87, 93-93, 99-99, 105-105

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/content/docs/3.architecture/1.overview.md` at line 12, Several fenced
code blocks in docs/content/docs/3.architecture/1.overview.md are unlabeled
(markdownlint MD040); update each unlabeled triple-backtick block (the blocks
containing flow diagrams like "Request → Auth Guard → Extract orgId..." and the
other five shown) to include an explicit language identifier such as text (e.g.,
change ``` to ```text) so the lint rule is satisfied and formatting is
consistent across the file.
docs/content/docs/2.configuration/2.database.md-14-14 (1)

14-14: ⚠️ Potential issue | 🟡 Minor

Specify fence languages for code blocks (markdownlint MD040).

Line 14, Line 32, and Line 93 use unlabeled fenced code blocks. Add explicit languages (bash/text/ts) to keep docs lint-clean.

Suggested fix
-```
+```bash
 DATABASE_URL=postgresql://user:password@localhost:5432/reqcore
-```
+```

-```
+```text
 organization (Better Auth)
 ...
-```
+```

-```
+```ts
 uniqueIndex(organizationId, email)
-```
+```

Also applies to: 32-32, 93-93

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/content/docs/2.configuration/2.database.md` at line 14, Three unlabeled
fenced code blocks need language tags: add ```bash for the block containing
"DATABASE_URL=postgresql://user:password@localhost:5432/reqcore", add ```text
for the block starting with "organization (Better Auth)" and add ```ts for the
block containing "uniqueIndex(organizationId, email)"; update those three fences
so the markdown uses explicit languages (bash, text, ts) to satisfy MD040.
i18n/locales/en.json-14-14 (1)

14-14: ⚠️ Potential issue | 🟡 Minor

Add the same home.nav.docs key to Spanish locale to avoid fallback text.

This new key is introduced here, but i18n/locales/es.json should also include home.nav.docs; otherwise Spanish users will see mixed-language navigation labels.

Suggested follow-up patch (outside this file)
# i18n/locales/es.json
 "home": {
   "nav": {
+    "docs": "Documentación",
     ...
   }
 }
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@i18n/locales/en.json` at line 14, The Spanish locale is missing the new
translation key "home.nav.docs", causing fallback to English; add the key
"home.nav.docs" to the Spanish locale JSON (i18n/locales/es.json) with the
appropriate Spanish translation (e.g., "Documentación" or "Docs") keeping the
same nested structure ("home" → "nav" → "docs") so Spanish users see the proper
label; update the file and run any i18n validation/linting to confirm no missing
keys remain.
docs/content/docs/3.architecture/2.data-model.md-12-21 (1)

12-21: ⚠️ Potential issue | 🟡 Minor

Add language identifiers to all fenced diagram/code blocks.

These blocks currently omit language tags and trigger MD040. Use text for ASCII diagrams/snippets.

Also applies to: 48-50, 73-75, 92-95

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/content/docs/3.architecture/2.data-model.md` around lines 12 - 21, Add
the missing language identifier "text" to the fenced code block that contains
the ASCII org/job/application diagram (the block starting with "organization
(Better Auth)" and its nested tree) so the fence becomes ```text, and apply the
same change to the other ASCII/code diagram fences referenced in the review (the
similar fenced blocks later in the file). Ensure every fenced block used for
diagrams/snippets uses the text language tag to satisfy MD040.
docs/content/docs/7.contributing/2.internationalization.md-37-46 (1)

37-46: ⚠️ Potential issue | 🟡 Minor

Add a language tag for the translation-files tree block.

Line 37 starts a fenced block without a language, which triggers MD040.

Proposed fix
-```
+```text
 i18n/
 └── locales/
     ├── en.json    # English (source of truth)
@@
     └── vi.json    # Vietnamese
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @docs/content/docs/7.contributing/2.internationalization.md around lines 37 -
46, Add a language tag to the fenced code block that contains the i18n directory
tree so the Markdown linter stops flagging MD040; specifically update the fenced
block that begins with the "i18n/" tree (the block showing locales including
en.json, nb.json, es.json, fr.json, de.json, vi.json) to use a language tag such
as "text" (i.e., change the opening totext).


</details>

</blockquote></details>
<details>
<summary>docs/content/docs/4.features/2.candidate-pipeline.md-12-15 (2)</summary><blockquote>

`12-15`: _⚠️ Potential issue_ | _🟡 Minor_

**Specify a language for the pipeline diagram fenced block.**

Line 12 starts a fenced block without a language, which triggers MD040.



<details>
<summary>Proposed fix</summary>

```diff
-```
+```text
 new → screening → interview → offer → hired
                                     → rejected
 ```
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @docs/content/docs/4.features/2.candidate-pipeline.md around lines 12 - 15,
The fenced code block for the pipeline diagram is missing a language specifier
and triggers MD040; update the block fence around the pipeline (the
triple-backtick block containing "new → screening → interview → offer → hired →
rejected") to include a language (e.g., add "text" after the opening ), so the block becomes text ... ``` to satisfy the linter.


</details>

---

`12-15`: _⚠️ Potential issue_ | _🟡 Minor_

**Pipeline transition diagram is too restrictive for `rejected`.**

The diagram currently suggests rejection only after `offer`, but Line 24 states rejection can happen at any stage, and `shared/status-transitions.ts` (Lines 19-26) also allows rejection from multiple stages.



<details>
<summary>Proposed fix</summary>

```diff
-```text
-new → screening → interview → offer → hired
-                                    → rejected
-```
+```text
+new       → screening → interview → offer → hired
+  ↘          ↘           ↘          ↘
+                rejected
+```
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @docs/content/docs/4.features/2.candidate-pipeline.md around lines 12 - 15,
The pipeline diagram in docs/content/docs/4.features/2.candidate-pipeline.md is
misleading because it shows rejection only after the offer while the text and
shared/status-transitions.ts allow rejection from multiple stages; update the
fenced code block diagram to visually show that "rejected" can branch from
earlier stages (e.g., from new, screening, interview, and offer) so the diagram
matches the prose and the transitions logic—edit the code block containing the
arrow diagram to the proposed multi-branch layout and ensure the fenced block
language marker (```text) and spacing align with surrounding markdown.


</details>

</blockquote></details>
<details>
<summary>docs/content/docs/1.getting-started/4.project-structure.md-12-50 (1)</summary><blockquote>

`12-50`: _⚠️ Potential issue_ | _🟡 Minor_

**Add a language tag to the directory-tree fenced block.**

Line 12 opens a fenced block without a language, which triggers MD040 and can fail markdown linting.



<details>
<summary>Proposed fix</summary>

```diff
-```
+```text
 reqcore/
 ├── app/                          # Client source (Nuxt 4 srcDir)
 ...
 └── package.json                  # Dependencies
 ```
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @docs/content/docs/1.getting-started/4.project-structure.md around lines 12 -
50, The fenced directory-tree block in
docs/content/docs/1.getting-started/4.project-structure.md is missing a language
tag (triggers MD040); update the opening triple-backtick for the block that
starts with "reqcore/" to include a language tag (e.g., ```text) so the tree is
treated as plain text; ensure the closing triple-backtick remains and run
markdownlint to confirm the MD040 warning is resolved.


</details>

</blockquote></details>
<details>
<summary>docs/content/docs/3.architecture/2.data-model.md-92-95 (1)</summary><blockquote>

`92-95`: _⚠️ Potential issue_ | _🟡 Minor_

**Application status diagram should reflect all valid `rejected` transitions.**

Current visualization suggests rejection only after `offer`, but transition logic allows rejection from earlier stages as well (see `shared/status-transitions.ts`, Lines 19-26).



<details>
<summary>Proposed fix</summary>

```diff
-```
-new → screening → interview → offer → hired
-                                    → rejected
-```
+```text
+new       → screening → interview → offer → hired
+  ↘          ↘           ↘          ↘
+                rejected
+```
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In `@docs/content/docs/3.architecture/2.data-model.md` around lines 92 - 95,
Update the ASCII application status diagram in
docs/content/docs/3.architecture/2.data-model.md so it reflects all valid
transitions to "rejected" as defined in shared/status-transitions.ts (the
transitions map involving statuses new, screening, interview, offer, hired,
rejected); modify the fenced code block to show rejection branches from earlier
stages (new, screening, interview, offer) pointing to rejected instead of only
from offer, using clear arrows and spacing so each transition is visible.
```

</details>

</blockquote></details>
<details>
<summary>docs/content/docs/1.getting-started/2.quick-start.md-67-69 (1)</summary><blockquote>

`67-69`: _⚠️ Potential issue_ | _🟡 Minor_

**Add a language tag to the startup-log fence block.**

Line 67 uses an unlabeled code fence (MD040).


<details>
<summary>Proposed fix</summary>

```diff
-```
+```text
 app  | Listening on http://[::]:3000
 ```
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @docs/content/docs/1.getting-started/2.quick-start.md around lines 67 - 69,
The unlabeled fenced code block containing the startup log line "app |
Listening on http://[::]:3000" needs a language tag to satisfy MD040; update
that fence from totext so the block becomes a labeled text code fence
(i.e., add "text" after the opening backticks for the code block that contains
the app startup log).


</details>

</blockquote></details>
<details>
<summary>docs/content/docs/2.configuration/3.storage.md-78-84 (1)</summary><blockquote>

`78-84`: _⚠️ Potential issue_ | _🟡 Minor_

**Add a language identifier to the architecture fence block.**

Line 78 uses a fenced code block without a language, which triggers MD040.


<details>
<summary>Proposed fix</summary>

```diff
-```
+```text
 Client → Authenticated API → Nitro Server → S3/MinIO
                                     ↓
                               Stream bytes
                                     ↓
                               Client receives file
 ```
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @docs/content/docs/2.configuration/3.storage.md around lines 78 - 84, The
fenced code block containing the ASCII architecture diagram (the block starting
with the lines "Client → Authenticated API → Nitro Server → S3/MinIO" and the
following arrows) needs a language identifier to satisfy MD040; change the
opening fence from totext so the block becomes a labeled text code
fence.


</details>

</blockquote></details>
<details>
<summary>docs/content/docs/2.configuration/4.authentication.md-12-15 (1)</summary><blockquote>

`12-15`: _⚠️ Potential issue_ | _🟡 Minor_

**Add a language tag to the flow diagram code block.**

Line 12 uses an unlabeled fenced block (MD040).


<details>
<summary>Proposed fix</summary>

```diff
-```
+```text
 Sign Up → Create Account → Create Organization → Dashboard
 Sign In → Session Cookie → Auth Middleware → Access Dashboard
 ```
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

Verify each finding against the current code and only fix it if needed.

In @docs/content/docs/2.configuration/4.authentication.md around lines 12 - 15,
The fenced code block containing the flow diagram (the two lines "Sign Up →
Create Account → Create Organization → Dashboard" and "Sign In → Session Cookie
→ Auth Middleware → Access Dashboard") is unlabeled, triggering MD040; update
the opening fence from totext so the block is explicitly tagged (i.e.,
add the language tag "text" after the opening backticks) to fix the lint
warning.


</details>

</blockquote></details>
<details>
<summary>docs/content/docs/1.getting-started/2.quick-start.md-53-55 (1)</summary><blockquote>

`53-55`: _⚠️ Potential issue_ | _🟡 Minor_

**Windows CMD instruction uses a non-CMD command.**

Line 54 says “Windows CMD / PowerShell” but uses `cp`, which is not available in `cmd.exe`.


<details>
<summary>Proposed fix</summary>

```diff
-**Windows CMD / PowerShell?** Run `cp .env.example .env` instead, then open `.env` and replace every placeholder value with a random string.
+**Windows CMD?** Run `copy .env.example .env`.
+**Windows PowerShell?** Run `Copy-Item .env.example .env`.
+Then open `.env` and replace every placeholder value with a random string.
```
</details>

<details>
<summary>🤖 Prompt for AI Agents</summary>

```
Verify each finding against the current code and only fix it if needed.

In `@docs/content/docs/1.getting-started/2.quick-start.md` around lines 53 - 55,
Update the callout that currently shows the Unix command `cp .env.example .env`
(inside the ::callout{icon="i-lucide-terminal" color="warning"} block) to
provide correct Windows equivalents: replace or augment the instruction so it
shows the CMD command `copy .env.example .env` for cmd.exe and the PowerShell
command `Copy-Item .env.example .env` (or note that PowerShell also supports
`cp`/`Copy-Item`), while keeping `cp .env.example .env` for Unix shells; ensure
the text clearly labels which command is for "Windows CMD" vs "PowerShell" vs
"macOS/Linux".
```

</details>

</blockquote></details>

</blockquote></details>

<details>
<summary>🧹 Nitpick comments (7)</summary><blockquote>

<details>
<summary>docs/content/docs/6.api/1.overview.md (1)</summary><blockquote>

`68-77`: **JSON code block contains invalid comment syntax.**

JSON doesn't support comments. Consider using separate code blocks or YAML with comments for clarity. Readers copy-pasting may encounter parse errors.


<details>
<summary>📝 Suggested fix</summary>

````diff
-```json
-// List
-[
-  { "id": "...", "title": "Senior Engineer", ... },
-  { "id": "...", "title": "Product Manager", ... }
-]
-
-// Single
-{ "id": "...", "title": "Senior Engineer", ... }
-```
+**List response:**
+
+```json
+[
+  { "id": "...", "title": "Senior Engineer" },
+  { "id": "...", "title": "Product Manager" }
+]
+```
+
+**Single resource response:**
+
+```json
+{ "id": "...", "title": "Senior Engineer" }
+```
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/content/docs/6.api/1.overview.md` around lines 68 - 77, Replace the
invalid commented JSON example with two valid code blocks: one showing the List
response as a JSON array and one showing the Single resource as a JSON object;
remove the inline comment markers ("// List", "// Single") and trailing
ellipses, ensure each block is fenced with ```json and contains valid JSON
(e.g., [{ "id": "...", "title": "Senior Engineer" }, { "id": "...", "title":
"Product Manager" }] and { "id": "...", "title": "Senior Engineer" }) so readers
can copy/paste without parse errors.
docs/content/docs/5.deployment/2.railway.md (1)

67-72: Clarify that BETTER_AUTH_URL is optional in preview environments.

The documentation suggests setting BETTER_AUTH_URL explicitly for preview environments, but the code in server/utils/auth.ts auto-resolves it from RAILWAY_PUBLIC_DOMAIN in PR/preview environments. It's only required in production. Consider noting this auto-resolution behavior to reduce configuration overhead for users.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/content/docs/5.deployment/2.railway.md` around lines 67 - 72, Update the
Preview Environments section in docs/content/docs/5.deployment/2.railway.md to
note that BETTER_AUTH_URL is optional for PR/preview deployments because
server/utils/auth.ts auto-resolves it from RAILWAY_PUBLIC_DOMAIN in preview/PR
environments; clarify that explicit BETTER_AUTH_URL is only required for
production deployments and mention the auto-resolution behavior (reference
server/utils/auth.ts) so users don’t need to set it for previews.
docs/content/docs/4.features/3.public-job-board.md (1)

28-28: Use “SEO” instead of “SEO Optimization” for tighter phrasing.

Line 28 is slightly redundant; “SEO” is sufficient and cleaner as a section title.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/content/docs/4.features/3.public-job-board.md` at line 28, Change the
section heading text "## SEO Optimization" to "## SEO" in the document so the
title is tighter and avoids redundancy; locate the header line that currently
reads "## SEO Optimization" and replace it with "## SEO".
nuxt.config.ts (1)

122-123: Validate docsUrl before exposing it to the client.

NUXT_PUBLIC_DOCS_URL is used directly. A malformed/non-http value can break navigation or create unsafe link targets.

Suggested hardening
+const defaultDocsUrl = 'https://docs.reqcore.com'
+const configuredDocsUrl = process.env.NUXT_PUBLIC_DOCS_URL || defaultDocsUrl
+const docsUrl = /^https?:\/\//i.test(configuredDocsUrl) ? configuredDocsUrl : defaultDocsUrl
+
 export default defineNuxtConfig({
@@
       /** URL for the documentation site — override with NUXT_PUBLIC_DOCS_URL in .env for local dev */
-      docsUrl: process.env.NUXT_PUBLIC_DOCS_URL || 'https://docs.reqcore.com',
+      docsUrl,
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@nuxt.config.ts` around lines 122 - 123, Validate NUXT_PUBLIC_DOCS_URL before
assigning it to docsUrl in the Nuxt config: implement a small validator (e.g.,
validateDocsUrl) used when setting docsUrl that attempts to construct a URL from
process.env.NUXT_PUBLIC_DOCS_URL and only returns it if the protocol is http or
https; otherwise fall back to the current literal 'https://docs.reqcore.com'.
Update the docsUrl assignment (the docsUrl symbol in nuxt.config.ts / inside
defineNuxtConfig) to call this validator so malformed or non-http values are
never exposed to the client.
app/pages/index.vue (1)

141-148: Unify docs destination across the page.

The header now uses config.public.docsUrl, but the footer still points to the GitHub README. Consider using the same runtime-configured URL in both places to avoid inconsistent navigation.

Suggested consistency update
-          <a
-            href="https://github.com/reqcore-inc/reqcore/blob/main/README.md"
+          <a
+            :href="config.public.docsUrl"
             target="_blank"
             rel="noopener noreferrer"
             class="transition hover:text-white"
           >
             Docs
           </a>
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@app/pages/index.vue` around lines 141 - 148, The footer currently hard-codes
the GitHub README URL while the header uses runtime config
(config.public.docsUrl); update the footer anchor(s) in app/pages/index.vue to
use the same runtime-config value by replacing the hard-coded href with
:href="config.public.docsUrl" (preserve target, rel and classes) and search for
any other README/GitHub docs anchors in this file to make them consistent as
well.
docs/nuxt.config.ts (1)

9-25: De-duplicate the docs base URL constant.

site.url and llms.domain duplicate the same literal. Pulling this into one constant reduces drift risk.

Proposed refactor
+const DOCS_URL = process.env.NUXT_PUBLIC_DOCS_URL || 'https://docs.reqcore.com'
+
 export default defineNuxtConfig({
   extends: ['docus'],
@@
   site: {
     name: 'Reqcore',
-    url: 'https://docs.reqcore.com',
+    url: DOCS_URL,
   },
@@
   llms: {
-    domain: 'https://docs.reqcore.com',
+    domain: DOCS_URL,
     title: 'Reqcore Documentation',
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/nuxt.config.ts` around lines 9 - 25, site.url and llms.domain are
duplicating the same literal; introduce a single constant (e.g., DOCS_BASE_URL
or BASE_URL) and replace both usages with that constant so the docs base URL is
defined once; update references in the nuxt config where site.url and
llms.domain are set (symbols: site.url, llms.domain) to use the new constant and
ensure any related descriptions remain unchanged.
docs/content/docs/1.getting-started/3.system-requirements.md (1)

54-59: Time-box the pricing table to avoid stale guidance.

Consider labeling these figures as estimates with a timestamp (for example, “as of March 2026”) so readers don’t treat them as current pricing indefinitely.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/content/docs/1.getting-started/3.system-requirements.md` around lines 54
- 59, The pricing table lacking a timestamp can become stale; update the
markdown table (the header row "Provider | Reference Setup | Monthly Cost" and
the cost cells for Hetzner, DigitalOcean, AWS EC2, Railway) to indicate these
are estimates and add a short timestamped note such as "Prices are estimates as
of March 2026" (or similar) directly below the table or as a footnote so each
cost cell is clearly labeled as approximate/estimated.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@docs/content/docs/2.configuration/1.environment-variables.md`:
- Around line 2-3: The docs claim a "complete reference" but the actual env
schema and public/runtime vars diverge; reconcile by either (A) updating the
Environment Variables doc to exactly mirror the validated server env schema
(include missing server vars BETTER_AUTH_TRUSTED_ORIGINS, TRUSTED_PROXY_IP,
RAILWAY_ENVIRONMENT_NAME, RAILWAY_GIT_PR_NUMBER, RAILWAY_PUBLIC_DOMAIN,
RESEND_API_KEY, RESEND_FROM_EMAIL) and remove items not present in the schema
(NUXT_PUBLIC_SITE_URL, LIVE_DEMO_EMAIL, LIVE_DEMO_SECRET), or (B) split the page
into two clear sections—"Validated server vars" (listing only variables
validated by the server schema) and "Public/runtime vars" (listing public-facing
NUXT_* and demo vars) — then update the page description and listings to match
the actual exported env schema and the runtime/public variables exactly.
- Around line 8-12: The doc claim "No runtime `process.env` access is allowed
outside `server/utils/env.ts`" is too absolute; update that sentence to say
runtime `process.env` access should be avoided and that validated access via
`server/utils/env.ts` is the standard, but that there are documented exceptions
(e.g., the jobs apply handler, migrations plugin, and seed script) which must be
either validated through the `env` utility or explicitly documented and audited;
change the wording to remove the absolute guarantee and add a short note
instructing developers to move any remaining direct `process.env` reads into
`server/utils/env.ts` or document/validate them as exceptions.

In `@docs/content/docs/2.configuration/4.authentication.md`:
- Around line 30-37: The example mis-destructures the result of requireAuth;
requireAuth returns an object with session where the active org id is at
session.session.activeOrganizationId, not orgId. Update the example in
server/api/jobs/index.get.ts to call const { session } = await
requireAuth(event) and derive the org id via
session.session.activeOrganizationId (or rename to activeOrganizationId) before
using it in the db.where clause so the code matches the actual return shape of
requireAuth.

In `@docs/content/docs/3.architecture/3.security.md`:
- Line 17: The docs incorrectly reference requireAuth(event); update the
security docs to show the correct auth guard pattern used by the codebase: call
requirePermission(event, { job: ['read'] }) (or appropriate permission set) and
retrieve orgId from session.session.activeOrganizationId returned by
server/utils/requirePermission.ts, replacing examples that destructure { orgId }
from requireAuth(event) so examples and lines 17 and 27–35 reflect the actual
API and usage.

In `@docs/package.json`:
- Around line 6-10: The docs package.json currently contains standalone
"scripts" entries ("build", "dev", "preview") but those are never invoked by CI
or image builds; add wiring so the docs build runs as part of the main build
pipeline: add a top-level script (e.g., "build:docs") to root package.json that
runs the docs build, or have the root build call npm/yarn with the docs prefix
(npm --prefix docs run build), then update the CI job that runs the root build
(pr-validation.yml) to invoke this new script and likewise ensure the Dockerfile
image build step executes the docs build (e.g., run npm --prefix docs run build
during image creation) so docs artifacts are produced and checked in CI; locate
the change by editing the docs package.json "scripts" block (build/dev/preview),
the root package.json scripts, the CI workflow job that executes the build, and
the Dockerfile build steps.

In `@docs/server/mcp/resources/architecture.ts`:
- Around line 1-6: The file path in the defineMcpResource call is incorrect:
update the file property on the exported defineMcpResource (the object with file
and metadata) to point to the repository root by changing '../ARCHITECTURE.md'
to '../../../ARCHITECTURE.md' so the resource correctly references
ARCHITECTURE.md at the repo root.

In `@docs/server/mcp/resources/changelog.ts`:
- Around line 1-6: The file path in the defineMcpResource call is incorrect;
update the file property in the defineMcpResource({...}) object (the "file"
field) to point to the repository-root CHANGELOG by changing '../CHANGELOG.md'
to '../../../../CHANGELOG.md' so the resource resolves to the actual file.

---

Minor comments:
In `@docs/content/docs/1.getting-started/2.quick-start.md`:
- Around line 67-69: The unlabeled fenced code block containing the startup log
line "app  | Listening on http://[::]:3000" needs a language tag to satisfy
MD040; update that fence from ``` to ```text so the block becomes a labeled text
code fence (i.e., add "text" after the opening backticks for the code block that
contains the app startup log).
- Around line 53-55: Update the callout that currently shows the Unix command
`cp .env.example .env` (inside the ::callout{icon="i-lucide-terminal"
color="warning"} block) to provide correct Windows equivalents: replace or
augment the instruction so it shows the CMD command `copy .env.example .env` for
cmd.exe and the PowerShell command `Copy-Item .env.example .env` (or note that
PowerShell also supports `cp`/`Copy-Item`), while keeping `cp .env.example .env`
for Unix shells; ensure the text clearly labels which command is for "Windows
CMD" vs "PowerShell" vs "macOS/Linux".

In `@docs/content/docs/1.getting-started/4.project-structure.md`:
- Around line 12-50: The fenced directory-tree block in
docs/content/docs/1.getting-started/4.project-structure.md is missing a language
tag (triggers MD040); update the opening triple-backtick for the block that
starts with "reqcore/" to include a language tag (e.g., ```text) so the tree is
treated as plain text; ensure the closing triple-backtick remains and run
markdownlint to confirm the MD040 warning is resolved.

In `@docs/content/docs/2.configuration/2.database.md`:
- Line 14: Three unlabeled fenced code blocks need language tags: add ```bash
for the block containing
"DATABASE_URL=postgresql://user:password@localhost:5432/reqcore", add ```text
for the block starting with "organization (Better Auth)" and add ```ts for the
block containing "uniqueIndex(organizationId, email)"; update those three fences
so the markdown uses explicit languages (bash, text, ts) to satisfy MD040.

In `@docs/content/docs/2.configuration/3.storage.md`:
- Around line 78-84: The fenced code block containing the ASCII architecture
diagram (the block starting with the lines "Client → Authenticated API → Nitro
Server → S3/MinIO" and the following arrows) needs a language identifier to
satisfy MD040; change the opening fence from ``` to ```text so the block becomes
a labeled text code fence.

In `@docs/content/docs/2.configuration/4.authentication.md`:
- Around line 12-15: The fenced code block containing the flow diagram (the two
lines "Sign Up → Create Account → Create Organization → Dashboard" and "Sign In
→ Session Cookie → Auth Middleware → Access Dashboard") is unlabeled, triggering
MD040; update the opening fence from ``` to ```text so the block is explicitly
tagged (i.e., add the language tag "text" after the opening backticks) to fix
the lint warning.

In `@docs/content/docs/3.architecture/1.overview.md`:
- Line 12: Several fenced code blocks in
docs/content/docs/3.architecture/1.overview.md are unlabeled (markdownlint
MD040); update each unlabeled triple-backtick block (the blocks containing flow
diagrams like "Request → Auth Guard → Extract orgId..." and the other five
shown) to include an explicit language identifier such as text (e.g., change ```
to ```text) so the lint rule is satisfied and formatting is consistent across
the file.

In `@docs/content/docs/3.architecture/2.data-model.md`:
- Around line 12-21: Add the missing language identifier "text" to the fenced
code block that contains the ASCII org/job/application diagram (the block
starting with "organization (Better Auth)" and its nested tree) so the fence
becomes ```text, and apply the same change to the other ASCII/code diagram
fences referenced in the review (the similar fenced blocks later in the file).
Ensure every fenced block used for diagrams/snippets uses the text language tag
to satisfy MD040.
- Around line 92-95: Update the ASCII application status diagram in
docs/content/docs/3.architecture/2.data-model.md so it reflects all valid
transitions to "rejected" as defined in shared/status-transitions.ts (the
transitions map involving statuses new, screening, interview, offer, hired,
rejected); modify the fenced code block to show rejection branches from earlier
stages (new, screening, interview, offer) pointing to rejected instead of only
from offer, using clear arrows and spacing so each transition is visible.

In `@docs/content/docs/4.features/1.job-management.md`:
- Around line 12-14: Update the fenced code block containing the ASCII diagram
"draft → open → closed → archived" to include a language specifier (e.g., text
or plaintext) so static analysis recognizes it as plain text; locate the block
with those exact contents and change the opening fence from ``` to ```text.

In `@docs/content/docs/4.features/2.candidate-pipeline.md`:
- Around line 12-15: The fenced code block for the pipeline diagram is missing a
language specifier and triggers MD040; update the block fence around the
pipeline (the triple-backtick block containing "new → screening → interview →
offer → hired → rejected") to include a language (e.g., add "text" after the
opening ```), so the block becomes ```text ... ``` to satisfy the linter.
- Around line 12-15: The pipeline diagram in
docs/content/docs/4.features/2.candidate-pipeline.md is misleading because it
shows rejection only after the offer while the text and
shared/status-transitions.ts allow rejection from multiple stages; update the
fenced code block diagram to visually show that "rejected" can branch from
earlier stages (e.g., from new, screening, interview, and offer) so the diagram
matches the prose and the transitions logic—edit the code block containing the
arrow diagram to the proposed multi-branch layout and ensure the fenced block
language marker (```text) and spacing align with surrounding markdown.

In `@docs/content/docs/5.deployment/1.self-hosting.md`:
- Around line 129-135: Replace the hardcoded database user/name in the example
backup/restore commands so they use the environment variables used in
docker-compose; update the pg_dump and psql invocations (the lines calling
pg_dump and psql) to use $DB_USER and $DB_NAME instead of the literal "reqcore",
and mention sourcing the .env (e.g., source .env) or replacing those variables
with your actual values so the commands match the ${DB_USER}/${DB_NAME} settings
from docker-compose.
- Around line 145-146: The example command hardcodes MinIO credentials (mc alias
set local http://localhost:9000 minioadmin minioadmin); update the documentation
to tell users to replace the hardcoded minioadmin/minioadmin with their actual
credentials by referencing the environment variables used in docker-compose:
$STORAGE_USER and $STORAGE_PASSWORD (e.g., "replace $STORAGE_USER and
$STORAGE_PASSWORD with the values from your .env file"). Ensure the note appears
immediately after the shown mc alias set line so readers know to substitute
their own credentials.

In `@docs/content/docs/5.deployment/2.railway.md`:
- Around line 57-58: The docs currently list the start command and omit
pre-deploy steps that differ from railway.json; update the documentation to
match railway.json by changing the start command from "node
.output/server/index.mjs" to "npm run start", keep the build command as "npm run
build", and add a note documenting the pre-deploy step: run "npm run db:migrate
&& npm run db:seed" (referencing railway.json keys startCommand and
preDeployCommand) so users know to run migrations and seed data before
deployment.

In `@docs/content/docs/5.deployment/3.docker.md`:
- Around line 54-66: Update the docs to reflect the actual Dockerfile
multi-stage setup: change the description from three stages to two, naming them
"builder" (which installs dependencies and runs nuxt build producing .output/)
and "runner" (which copies .output and runs node .output/server/index.mjs);
remove or reword the separate "Dependencies" stage and ensure text accurately
states that the builder performs both install and build steps so the
documentation matches the Dockerfile.

In `@docs/content/docs/7.contributing/2.internationalization.md`:
- Around line 37-46: Add a language tag to the fenced code block that contains
the i18n directory tree so the Markdown linter stops flagging MD040;
specifically update the fenced block that begins with the "i18n/" tree (the
block showing locales including en.json, nb.json, es.json, fr.json, de.json,
vi.json) to use a language tag such as "text" (i.e., change the opening ``` to
```text).

In `@i18n/locales/en.json`:
- Line 14: The Spanish locale is missing the new translation key
"home.nav.docs", causing fallback to English; add the key "home.nav.docs" to the
Spanish locale JSON (i18n/locales/es.json) with the appropriate Spanish
translation (e.g., "Documentación" or "Docs") keeping the same nested structure
("home" → "nav" → "docs") so Spanish users see the proper label; update the file
and run any i18n validation/linting to confirm no missing keys remain.

---

Nitpick comments:
In `@app/pages/index.vue`:
- Around line 141-148: The footer currently hard-codes the GitHub README URL
while the header uses runtime config (config.public.docsUrl); update the footer
anchor(s) in app/pages/index.vue to use the same runtime-config value by
replacing the hard-coded href with :href="config.public.docsUrl" (preserve
target, rel and classes) and search for any other README/GitHub docs anchors in
this file to make them consistent as well.

In `@docs/content/docs/1.getting-started/3.system-requirements.md`:
- Around line 54-59: The pricing table lacking a timestamp can become stale;
update the markdown table (the header row "Provider | Reference Setup | Monthly
Cost" and the cost cells for Hetzner, DigitalOcean, AWS EC2, Railway) to
indicate these are estimates and add a short timestamped note such as "Prices
are estimates as of March 2026" (or similar) directly below the table or as a
footnote so each cost cell is clearly labeled as approximate/estimated.

In `@docs/content/docs/4.features/3.public-job-board.md`:
- Line 28: Change the section heading text "## SEO Optimization" to "## SEO" in
the document so the title is tighter and avoids redundancy; locate the header
line that currently reads "## SEO Optimization" and replace it with "## SEO".

In `@docs/content/docs/5.deployment/2.railway.md`:
- Around line 67-72: Update the Preview Environments section in
docs/content/docs/5.deployment/2.railway.md to note that BETTER_AUTH_URL is
optional for PR/preview deployments because server/utils/auth.ts auto-resolves
it from RAILWAY_PUBLIC_DOMAIN in preview/PR environments; clarify that explicit
BETTER_AUTH_URL is only required for production deployments and mention the
auto-resolution behavior (reference server/utils/auth.ts) so users don’t need to
set it for previews.

In `@docs/content/docs/6.api/1.overview.md`:
- Around line 68-77: Replace the invalid commented JSON example with two valid
code blocks: one showing the List response as a JSON array and one showing the
Single resource as a JSON object; remove the inline comment markers ("// List",
"// Single") and trailing ellipses, ensure each block is fenced with ```json and
contains valid JSON (e.g., [{ "id": "...", "title": "Senior Engineer" }, { "id":
"...", "title": "Product Manager" }] and { "id": "...", "title": "Senior
Engineer" }) so readers can copy/paste without parse errors.

In `@docs/nuxt.config.ts`:
- Around line 9-25: site.url and llms.domain are duplicating the same literal;
introduce a single constant (e.g., DOCS_BASE_URL or BASE_URL) and replace both
usages with that constant so the docs base URL is defined once; update
references in the nuxt config where site.url and llms.domain are set (symbols:
site.url, llms.domain) to use the new constant and ensure any related
descriptions remain unchanged.

In `@nuxt.config.ts`:
- Around line 122-123: Validate NUXT_PUBLIC_DOCS_URL before assigning it to
docsUrl in the Nuxt config: implement a small validator (e.g., validateDocsUrl)
used when setting docsUrl that attempts to construct a URL from
process.env.NUXT_PUBLIC_DOCS_URL and only returns it if the protocol is http or
https; otherwise fall back to the current literal 'https://docs.reqcore.com'.
Update the docsUrl assignment (the docsUrl symbol in nuxt.config.ts / inside
defineNuxtConfig) to call this validator so malformed or non-http values are
never exposed to the client.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro

Run ID: 7536b32a-0349-4e9b-86e0-b7ac45ef7f31

📥 Commits

Reviewing files that changed from the base of the PR and between 94b5cda and ce2a0eb.

⛔ Files ignored due to path filters (3)
  • docs/package-lock.json is excluded by !**/package-lock.json
  • docs/public/logo-dark.svg is excluded by !**/*.svg
  • docs/public/logo-light.svg is excluded by !**/*.svg
📒 Files selected for processing (40)
  • .env.example
  • README.md
  • app/pages/index.vue
  • docs/.gitignore
  • docs/app/app.config.ts
  • docs/content/docs/1.getting-started/1.introduction.md
  • docs/content/docs/1.getting-started/2.quick-start.md
  • docs/content/docs/1.getting-started/3.system-requirements.md
  • docs/content/docs/1.getting-started/4.project-structure.md
  • docs/content/docs/2.configuration/1.environment-variables.md
  • docs/content/docs/2.configuration/2.database.md
  • docs/content/docs/2.configuration/3.storage.md
  • docs/content/docs/2.configuration/4.authentication.md
  • docs/content/docs/3.architecture/1.overview.md
  • docs/content/docs/3.architecture/2.data-model.md
  • docs/content/docs/3.architecture/3.security.md
  • docs/content/docs/4.features/1.job-management.md
  • docs/content/docs/4.features/2.candidate-pipeline.md
  • docs/content/docs/4.features/3.public-job-board.md
  • docs/content/docs/4.features/4.dashboard.md
  • docs/content/docs/5.deployment/1.self-hosting.md
  • docs/content/docs/5.deployment/2.railway.md
  • docs/content/docs/5.deployment/3.docker.md
  • docs/content/docs/6.api/1.overview.md
  • docs/content/docs/7.contributing/1.development-setup.md
  • docs/content/docs/7.contributing/2.internationalization.md
  • docs/content/docs/8.faq.md
  • docs/content/index.md
  • docs/nuxt.config.ts
  • docs/package.json
  • docs/server/mcp/resources/architecture.ts
  • docs/server/mcp/resources/changelog.ts
  • docs/server/mcp/resources/roadmap.ts
  • docs/tsconfig.json
  • i18n/locales/de.json
  • i18n/locales/en.json
  • i18n/locales/fr.json
  • i18n/locales/nb.json
  • i18n/locales/vi.json
  • nuxt.config.ts

Comment on lines +2 to +3
title: 'Environment Variables'
description: 'Complete reference for all environment variables used by Reqcore, with defaults and validation rules.'
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

“Complete reference” wording does not match actual env schema.

The page states a complete reference with validation rules, but server/utils/env.ts:37-92 includes variables missing here (e.g., BETTER_AUTH_TRUSTED_ORIGINS, TRUSTED_PROXY_IP, RAILWAY_ENVIRONMENT_NAME, RAILWAY_GIT_PR_NUMBER, RAILWAY_PUBLIC_DOMAIN, RESEND_API_KEY, RESEND_FROM_EMAIL), while this page lists items not in that schema (NUXT_PUBLIC_SITE_URL, LIVE_DEMO_EMAIL, LIVE_DEMO_SECRET). Please reconcile docs vs schema (or split “validated server vars” vs “runtime/public vars” explicitly).

Also applies to: 41-54

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/content/docs/2.configuration/1.environment-variables.md` around lines 2
- 3, The docs claim a "complete reference" but the actual env schema and
public/runtime vars diverge; reconcile by either (A) updating the Environment
Variables doc to exactly mirror the validated server env schema (include missing
server vars BETTER_AUTH_TRUSTED_ORIGINS, TRUSTED_PROXY_IP,
RAILWAY_ENVIRONMENT_NAME, RAILWAY_GIT_PR_NUMBER, RAILWAY_PUBLIC_DOMAIN,
RESEND_API_KEY, RESEND_FROM_EMAIL) and remove items not present in the schema
(NUXT_PUBLIC_SITE_URL, LIVE_DEMO_EMAIL, LIVE_DEMO_SECRET), or (B) split the page
into two clear sections—"Validated server vars" (listing only variables
validated by the server schema) and "Public/runtime vars" (listing public-facing
NUXT_* and demo vars) — then update the page description and listings to match
the actual exported env schema and the runtime/public variables exactly.

Comment on lines +8 to +12
All environment variables are validated at startup using Zod in `server/utils/env.ts`. If any required variable is missing or malformed, the server fails immediately with a clear error message.

::callout{icon="i-lucide-shield" color="warning"}
**Security**: No runtime `process.env` access is allowed outside `server/utils/env.ts`. All environment access goes through the validated `env` utility.
::
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Security/validation guarantee is currently inaccurate.

Line 11 says no runtime process.env access exists outside server/utils/env.ts, but current code does access it directly (e.g., server/api/public/jobs/[slug]/apply.post.ts:47-48, server/plugins/migrations.ts:1-10, server/scripts/seed.ts:1-20). Please relax or correct this claim.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/content/docs/2.configuration/1.environment-variables.md` around lines 8
- 12, The doc claim "No runtime `process.env` access is allowed outside
`server/utils/env.ts`" is too absolute; update that sentence to say runtime
`process.env` access should be avoided and that validated access via
`server/utils/env.ts` is the standard, but that there are documented exceptions
(e.g., the jobs apply handler, migrations plugin, and seed script) which must be
either validated through the `env` utility or explicitly documented and audited;
change the wording to remove the absolute guarantee and add a short note
instructing developers to move any remaining direct `process.env` reads into
`server/utils/env.ts` or document/validate them as exceptions.

Comment on lines +30 to +37
```ts
// server/api/jobs/index.get.ts
export default defineEventHandler(async (event) => {
const { session, orgId } = await requireAuth(event)
// session is guaranteed valid, orgId is the active organization
const jobs = await db.select().from(schema.job)
.where(eq(schema.job.organizationId, orgId))
return jobs
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

requireAuth usage example does not match actual return shape.

Line 33 destructures orgId, but server/utils/requireAuth.ts:1-39 returns session.session.activeOrganizationId (no orgId property). This example will mislead implementers.

Proposed fix
 export default defineEventHandler(async (event) => {
-  const { session, orgId } = await requireAuth(event)
-  // session is guaranteed valid, orgId is the active organization
+  const session = await requireAuth(event)
+  const orgId = session.session.activeOrganizationId
+  // session is guaranteed valid, orgId is the active organization
   const jobs = await db.select().from(schema.job)
     .where(eq(schema.job.organizationId, orgId))
   return jobs
 })
📝 Committable suggestion

‼️ IMPORTANT
Carefully review the code before committing. Ensure that it accurately replaces the highlighted code, contains no missing lines, and has no issues with indentation. Thoroughly test & benchmark the code to ensure it meets the requirements.

Suggested change
```ts
// server/api/jobs/index.get.ts
export default defineEventHandler(async (event) => {
const { session, orgId } = await requireAuth(event)
// session is guaranteed valid, orgId is the active organization
const jobs = await db.select().from(schema.job)
.where(eq(schema.job.organizationId, orgId))
return jobs
// server/api/jobs/index.get.ts
export default defineEventHandler(async (event) => {
const session = await requireAuth(event)
const orgId = session.session.activeOrganizationId
// session is guaranteed valid, orgId is the active organization
const jobs = await db.select().from(schema.job)
.where(eq(schema.job.organizationId, orgId))
return jobs
})
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/content/docs/2.configuration/4.authentication.md` around lines 30 - 37,
The example mis-destructures the result of requireAuth; requireAuth returns an
object with session where the active org id is at
session.session.activeOrganizationId, not orgId. Update the example in
server/api/jobs/index.get.ts to call const { session } = await
requireAuth(event) and derive the org id via
session.session.activeOrganizationId (or rename to activeOrganizationId) before
using it in the db.where clause so the code matches the actual return shape of
requireAuth.

| **Session management** | HTTP-only cookies via Better Auth |
| **Password hashing** | Argon2id (Better Auth default) |
| **CSRF protection** | Origin header validation |
| **Auth guard** | `requireAuth(event)` on every protected endpoint |
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Security guidance references the wrong auth guard API.

Line 17 and Line 29 currently document requireAuth(event), but the enforced pattern in server/utils/requirePermission.ts returns session.session.activeOrganizationId. This mismatch can lead to incorrect access-control implementations.

Suggested fix
-| **Auth guard** | `requireAuth(event)` on every protected endpoint |
+| **Auth guard** | `requirePermission(event, permissions)` on every protected endpoint |

 ```ts
 // ✅ Correct: orgId comes from session
-const { orgId } = await requireAuth(event)
+const session = await requirePermission(event, { job: ['read'] })
+const orgId = session.session.activeOrganizationId
 const jobs = await db.select().from(schema.job)
   .where(eq(schema.job.organizationId, orgId))

Also applies to: 27-35

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/content/docs/3.architecture/3.security.md` at line 17, The docs
incorrectly reference requireAuth(event); update the security docs to show the
correct auth guard pattern used by the codebase: call requirePermission(event, {
job: ['read'] }) (or appropriate permission set) and retrieve orgId from
session.session.activeOrganizationId returned by
server/utils/requirePermission.ts, replacing examples that destructure { orgId }
from requireAuth(event) so examples and lines 17 and 27–35 reflect the actual
API and usage.

Comment thread docs/package.json
Comment on lines +6 to +10
"scripts": {
"build": "nuxt build",
"dev": "nuxt dev",
"preview": "nuxt preview"
},
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

Docs app build is currently disconnected from CI and image build.

docs/package.json defines its own build, but current pipeline/build steps only run root npm run build (see .github/workflows/pr-validation.yml:30-56, Dockerfile:1-16, package.json:5-25). This allows docs regressions to merge undetected and prevents docs artifacts from being built in container workflows.

Suggested pipeline wiring
# .github/workflows/pr-validation.yml
+      - name: Install docs dependencies
+        run: npm --prefix docs ci
+
+      - name: Build docs
+        run: npm --prefix docs run build
# Dockerfile (builder stage)
 RUN npm run build
+RUN npm --prefix docs ci && npm --prefix docs run build
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/package.json` around lines 6 - 10, The docs package.json currently
contains standalone "scripts" entries ("build", "dev", "preview") but those are
never invoked by CI or image builds; add wiring so the docs build runs as part
of the main build pipeline: add a top-level script (e.g., "build:docs") to root
package.json that runs the docs build, or have the root build call npm/yarn with
the docs prefix (npm --prefix docs run build), then update the CI job that runs
the root build (pr-validation.yml) to invoke this new script and likewise ensure
the Dockerfile image build step executes the docs build (e.g., run npm --prefix
docs run build during image creation) so docs artifacts are produced and checked
in CI; locate the change by editing the docs package.json "scripts" block
(build/dev/preview), the root package.json scripts, the CI workflow job that
executes the build, and the Dockerfile build steps.

Comment on lines +1 to +6
export default defineMcpResource({
file: '../ARCHITECTURE.md',
metadata: {
description: 'Reqcore system architecture — tech stack, data model, security boundaries, and deployment.',
},
})
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🔴 Critical

🧩 Analysis chain

🏁 Script executed:

#!/bin/bash

# Find all ARCHITECTURE.md files
echo "=== Locating ARCHITECTURE.md files ==="
fd -t f "ARCHITECTURE.md"

# Check the directory structure of docs/server/mcp/
echo -e "\n=== Directory structure of docs/server/mcp/ ==="
if [ -d "docs/server/mcp" ]; then
  tree -L 3 "docs/server/mcp" 2>/dev/null || find docs/server/mcp -type f -o -type d | head -30
fi

# Verify the actual location relative to docs/server/mcp/resources/
echo -e "\n=== Checking docs/server/mcp/ contents ==="
ls -la docs/server/mcp/ 2>/dev/null || echo "Directory not found"

echo -e "\n=== Checking docs/server/mcp/resources/ contents ==="
ls -la docs/server/mcp/resources/ 2>/dev/null || echo "Directory not found"

Repository: reqcore-inc/reqcore

Length of output: 843


🏁 Script executed:

#!/bin/bash

# Get full path of ARCHITECTURE.md
echo "=== Full path to ARCHITECTURE.md ==="
fd -t f "ARCHITECTURE.md" -x echo {}

# Also try direct locate
echo -e "\n=== Attempting to find ARCHITECTURE.md with absolute path ==="
find . -name "ARCHITECTURE.md" -type f

# Check if it's in the root or other locations
echo -e "\n=== Check repo root for ARCHITECTURE.md ==="
ls -la ARCHITECTURE.md 2>/dev/null || echo "Not in root"

Repository: reqcore-inc/reqcore

Length of output: 309


Update relative path to correctly reference ARCHITECTURE.md at repository root.

The relative path ../ARCHITECTURE.md resolves to docs/server/mcp/ARCHITECTURE.md, but ARCHITECTURE.md is located at the repository root. Update the path to ../../../ARCHITECTURE.md to correctly reference the file.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/server/mcp/resources/architecture.ts` around lines 1 - 6, The file path
in the defineMcpResource call is incorrect: update the file property on the
exported defineMcpResource (the object with file and metadata) to point to the
repository root by changing '../ARCHITECTURE.md' to '../../../ARCHITECTURE.md'
so the resource correctly references ARCHITECTURE.md at the repo root.

Comment on lines +1 to +6
export default defineMcpResource({
file: '../CHANGELOG.md',
metadata: {
description: 'Reqcore changelog — version history and release notes for the open-source ATS.',
},
})
Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

⚠️ Potential issue | 🟠 Major

🧩 Analysis chain

🏁 Script executed:

fd -t f "CHANGELOG.md"

Repository: reqcore-inc/reqcore

Length of output: 75


Fix the relative path to CHANGELOG.md — it should be ../../../../CHANGELOG.md.

The file CHANGELOG.md is at the repository root. The current path ../CHANGELOG.md would resolve to docs/server/mcp/CHANGELOG.md, which doesn't exist. Correct it to reach the actual file location.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@docs/server/mcp/resources/changelog.ts` around lines 1 - 6, The file path in
the defineMcpResource call is incorrect; update the file property in the
defineMcpResource({...}) object (the "file" field) to point to the
repository-root CHANGELOG by changing '../CHANGELOG.md' to
'../../../../CHANGELOG.md' so the resource resolves to the actual file.

@JoachimLK JoachimLK closed this Mar 5, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant