Skip to content

Commit 791251f

Browse files
committed
feat: refactor framework to stack terminology across the application; update related data structures and templates
1 parent c6cce94 commit 791251f

File tree

14 files changed

+87
-87
lines changed

14 files changed

+87
-87
lines changed

README.md

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -6,13 +6,13 @@ Build high-signal agent and instruction files from community-proven best practic
66

77
## What devcontext does
88
- Transforms curated community knowledge into ready-to-use instructions for agents, coding copilots, and repo guides.
9-
- Guides you through a multi-step wizard that selects files, frameworks, and scenario-specific topics.
9+
- Guides you through a multi-step wizard that selects files, stacks, and scenario-specific topics.
1010
- Surfaces examples, trade-offs, and documentation links so every choice is backed by trusted references.
1111

1212
## How the wizard works
1313
1. Launch the app and switch from the landing hero to the Instructions Wizard.
1414
2. Pick the instruction file you want to assemble (from templates defined in `data/files.json`).
15-
3. Choose your framework and automatically load its follow-up question set (dynamic imports from `data/questions/<framework>.json`).
15+
3. Choose your stack and automatically load its follow-up question set (dynamic imports from `data/questions/<stack>.json`).
1616
4. Answer topic prompts across general, architecture, performance, security, commits, and more—or lean on the recommended defaults when you need a fast decision.
1717
5. Review a completion summary that highlights what made it into your file and which areas still need decisions.
1818

@@ -38,7 +38,7 @@ Then open the printed local URL in your browser to explore the wizard.
3838

3939
## Contribute back to the community
4040
- Add or improve topics in `data/*.json` with clear labels, examples, and `docs` links.
41-
- Propose new framework questionnaires under `data/questions/`, keeping the schema consistent.
41+
- Propose new stack questionnaires under `data/questions/`, keeping the schema consistent.
4242
- Share hooks, utilities, or UI refinements that make the wizard easier to reason about for first-time contributors.
4343

4444
Every addition helps the community build better instruction files faster.

agents.md

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -8,8 +8,8 @@
88
- Entry point at `app/page.tsx` toggles between a marketing hero and the instructions wizard.
99
- Wizard steps currently cover:
1010
- Instructions file selection (`data/files.json`).
11-
- Framework selection (`data/frameworks.json`) with branching into framework-specific question sets (e.g., `data/questions/react.json`).
12-
- Dynamic question sets loaded via `import()` based on the chosen framework.
11+
- Stack selection (`data/stacks.json`) with branching into stack-specific question sets (e.g., `data/questions/react.json`).
12+
- Dynamic question sets loaded via `import()` based on the chosen stack.
1313
- User actions per question:
1414
- Select single or multiple answers, or apply the recommended default when unsure.
1515
- Review hover tooltips with examples, pros/cons, tags, and documentation links.
@@ -18,8 +18,8 @@
1818
## Data Conventions
1919
- Every answer object may define: `value`, `label`, `icon`, `example`, `infoLines` (derived from `pros`/`cons`), `tags`, `isDefault`, `disabled`, `disabledLabel`, and `docs`.
2020
- JSON files in `data/` supply domain-specific options:
21-
- `files.json`, `frameworks.json`, `general.json`, `architecture.json`, `performance.json`, `security.json`, `commits.json`.
22-
- Framework-specific questionnaires live in `data/questions/<framework>.json`.
21+
- `files.json`, `stacks.json`, `general.json`, `architecture.json`, `performance.json`, `security.json`, `commits.json`.
22+
- Stack-specific questionnaires live in `data/questions/<stack>.json`.
2323
- Newly added `docs` fields should point to authoritative resources and are surfaced in tooltips as external links.
2424

2525
## Visual & Interaction Details (components/instructions-wizard.tsx)
@@ -31,7 +31,7 @@
3131

3232
## Extending the Wizard
3333
1. Add new answer sets to relevant JSON files with `docs` links when possible.
34-
2. For additional frameworks, create `data/questions/<framework>.json` and ensure the `docs` field on the framework entry is populated.
34+
2. For additional stacks, create `data/questions/<stack>.json` and ensure the `docs` field on the stack entry is populated.
3535
3. The wizard automatically consumes new questions when they follow the existing schema.
3636

3737
## Development Workflow

app/api/generate/[framework]/[fileName]/route.ts

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,15 +31,15 @@ export async function POST(
3131

3232
const templateKeyFromParams: TemplateKey = {
3333
templateType: mapOutputFileToTemplateType(fileName),
34-
framework: frameworkFromPath,
34+
stack: frameworkFromPath,
3535
}
3636

3737
let templateConfig = getTemplateConfig(templateKeyFromParams)
3838

3939
if (!templateConfig && responses.outputFile) {
4040
const templateKeyFromBody: TemplateKey = {
4141
templateType: mapOutputFileToTemplateType(responses.outputFile),
42-
framework: responses.frameworkSelection || undefined,
42+
stack: responses.stackSelection || undefined,
4343
}
4444

4545
templateConfig = getTemplateConfig(templateKeyFromBody)
@@ -86,7 +86,7 @@ export async function POST(
8686
}
8787
}
8888

89-
replaceVariable('frameworkSelection')
89+
replaceVariable('stackSelection')
9090
replaceVariable('tooling')
9191
replaceVariable('language')
9292
replaceVariable('projectPriority')

app/new/page.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -83,7 +83,7 @@ export default function NewInstructionsPage() {
8383
</p>
8484
<div className="mx-auto max-w-2xl text-left text-sm text-muted-foreground/90 md:text-base">
8585
<ul className="list-disc space-y-2 pl-5">
86-
<li>Pick a preset to load framework, architecture, and workflow prompts.</li>
86+
<li>Pick a preset to load stack, architecture, and workflow prompts.</li>
8787
<li>Answer or skip questions — you can revisit any step before exporting.</li>
8888
<li>Download the generated file once every section shows as complete.</li>
8989
</ul>

components/instructions-wizard.tsx

Lines changed: 50 additions & 50 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import { Button } from "@/components/ui/button"
55
import { Undo2 } from "lucide-react"
66

77
import type { DataQuestionSource, FileOutputConfig, InstructionsWizardProps, Responses, WizardAnswer, WizardConfirmationIntent, WizardQuestion, WizardStep } from "@/types/wizard"
8-
import frameworksData from "@/data/frameworks.json"
8+
import stacksData from "@/data/stacks.json"
99
import generalData from "@/data/general.json"
1010
import architectureData from "@/data/architecture.json"
1111
import performanceData from "@/data/performance.json"
@@ -24,17 +24,17 @@ import { serializeWizardResponses } from "@/lib/wizard-response"
2424
import { buildFileOptionsFromQuestion, buildStepFromQuestionSet, getFormatLabel, mapAnswerSourceToWizard } from "@/lib/wizard-utils"
2525
import type { GeneratedFileResult } from "@/types/output"
2626

27-
const FRAMEWORK_STEP_ID = "frameworks"
28-
const FRAMEWORK_QUESTION_ID = "frameworkSelection"
27+
const STACK_STEP_ID = "stacks"
28+
const STACK_QUESTION_ID = "stackSelection"
2929
const DEVCONTEXT_ROOT_URL = "https://devcontext.xyz/"
3030

31-
const frameworkQuestionSet = frameworksData as DataQuestionSource[]
32-
const frameworksStep = buildStepFromQuestionSet(
33-
FRAMEWORK_STEP_ID,
34-
"Choose Your Framework",
35-
frameworkQuestionSet
31+
const stackQuestionSet = stacksData as DataQuestionSource[]
32+
const stacksStep = buildStepFromQuestionSet(
33+
STACK_STEP_ID,
34+
"Choose Your Stack",
35+
stackQuestionSet
3636
)
37-
const frameworkQuestion = frameworksStep.questions.find((question) => question.id === FRAMEWORK_QUESTION_ID) ?? null
37+
const stackQuestion = stacksStep.questions.find((question) => question.id === STACK_QUESTION_ID) ?? null
3838

3939
const fileQuestionSet = filesData as DataQuestionSource[]
4040
const fileQuestion = fileQuestionSet[0] ?? null
@@ -98,7 +98,7 @@ export function InstructionsWizard({ onClose, selectedFileId }: InstructionsWiza
9898
const [pendingConfirmation, setPendingConfirmation] = useState<WizardConfirmationIntent | null>(null)
9999
const [generatedFile, setGeneratedFile] = useState<GeneratedFileResult | null>(null)
100100
const [isGenerating, setIsGenerating] = useState(false)
101-
const [isFrameworkFastTrackPromptVisible, setIsFrameworkFastTrackPromptVisible] = useState(false)
101+
const [isStackFastTrackPromptVisible, setIsStackFastTrackPromptVisible] = useState(false)
102102
const [autoFilledQuestionMap, setAutoFilledQuestionMap] = useState<Record<string, boolean>>({})
103103
const [autoFillNotice, setAutoFillNotice] = useState<string | null>(null)
104104
const [activeEditQuestionId, setActiveEditQuestionId] = useState<string | null>(null)
@@ -126,12 +126,12 @@ export function InstructionsWizard({ onClose, selectedFileId }: InstructionsWiza
126126
)
127127

128128
const wizardSteps = useMemo(
129-
() => [frameworksStep, ...dynamicSteps, ...suffixSteps],
129+
() => [stacksStep, ...dynamicSteps, ...suffixSteps],
130130
[dynamicSteps]
131131
)
132132

133-
const nonFrameworkSteps = useMemo(
134-
() => wizardSteps.filter((step) => step.id !== FRAMEWORK_STEP_ID),
133+
const nonStackSteps = useMemo(
134+
() => wizardSteps.filter((step) => step.id !== STACK_STEP_ID),
135135
[wizardSteps]
136136
)
137137

@@ -159,8 +159,8 @@ export function InstructionsWizard({ onClose, selectedFileId }: InstructionsWiza
159159
)
160160

161161
const remainingQuestionCount = useMemo(
162-
() => nonFrameworkSteps.reduce((count, step) => count + step.questions.length, 0),
163-
[nonFrameworkSteps]
162+
() => nonStackSteps.reduce((count, step) => count + step.questions.length, 0),
163+
[nonStackSteps]
164164
)
165165

166166
const completionSummary = useMemo(
@@ -207,8 +207,8 @@ export function InstructionsWizard({ onClose, selectedFileId }: InstructionsWiza
207207
? `Use default (${defaultAnswer.label})`
208208
: "Use default"
209209

210-
const showFrameworkPivot = !isComplete && isFrameworkFastTrackPromptVisible
211-
const showQuestionControls = !isComplete && !isFrameworkFastTrackPromptVisible
210+
const showStackPivot = !isComplete && isStackFastTrackPromptVisible
211+
const showQuestionControls = !isComplete && !isStackFastTrackPromptVisible
212212

213213
const markQuestionsAutoFilled = useCallback((questionIds: string[]) => {
214214
if (questionIds.length === 0) {
@@ -218,7 +218,7 @@ export function InstructionsWizard({ onClose, selectedFileId }: InstructionsWiza
218218
setAutoFilledQuestionMap((prev) => {
219219
const next = { ...prev }
220220
questionIds.forEach((id) => {
221-
if (id !== FRAMEWORK_QUESTION_ID) {
221+
if (id !== STACK_QUESTION_ID) {
222222
next[id] = true
223223
}
224224
})
@@ -273,8 +273,8 @@ export function InstructionsWizard({ onClose, selectedFileId }: InstructionsWiza
273273
}
274274

275275
const goToPrevious = () => {
276-
if (isFrameworkFastTrackPromptVisible) {
277-
setIsFrameworkFastTrackPromptVisible(false)
276+
if (isStackFastTrackPromptVisible) {
277+
setIsStackFastTrackPromptVisible(false)
278278
}
279279

280280
const isFirstQuestionInStep = currentQuestionIndex === 0
@@ -297,11 +297,11 @@ export function InstructionsWizard({ onClose, selectedFileId }: InstructionsWiza
297297
setIsComplete(false)
298298
}
299299

300-
const loadFrameworkQuestions = async (frameworkId: string, frameworkLabel?: string) => {
300+
const loadStackQuestions = async (stackId: string, stackLabel?: string) => {
301301
try {
302302
setGeneratedFile(null)
303303

304-
const questionsModule = await import(`@/data/questions/${frameworkId}.json`)
304+
const questionsModule = await import(`@/data/questions/${stackId}.json`)
305305
const questionsData = (questionsModule.default ?? questionsModule) as DataQuestionSource[]
306306

307307
const mappedQuestions: WizardQuestion[] = questionsData.map((question) => ({
@@ -318,18 +318,18 @@ export function InstructionsWizard({ onClose, selectedFileId }: InstructionsWiza
318318
setAutoFilledQuestionMap({})
319319
setAutoFillNotice(null)
320320

321-
const resolvedFrameworkLabel =
322-
frameworkLabel ?? frameworkQuestion?.answers.find((answer) => answer.value === frameworkId)?.label ?? frameworkId
321+
const resolvedStackLabel =
322+
stackLabel ?? stackQuestion?.answers.find((answer) => answer.value === stackId)?.label ?? stackId
323323

324324
setDynamicSteps([
325325
{
326-
id: `framework-${frameworkId}`,
327-
title: `${resolvedFrameworkLabel} Preferences`,
326+
id: `stack-${stackId}`,
327+
title: `${resolvedStackLabel} Preferences`,
328328
questions: mappedQuestions,
329329
},
330330
])
331331

332-
setIsFrameworkFastTrackPromptVisible(followUpQuestionCount > 0)
332+
setIsStackFastTrackPromptVisible(followUpQuestionCount > 0)
333333

334334
setResponses((prev) => {
335335
const next = { ...prev }
@@ -343,9 +343,9 @@ export function InstructionsWizard({ onClose, selectedFileId }: InstructionsWiza
343343
setCurrentQuestionIndex(0)
344344
setIsComplete(false)
345345
} catch (error) {
346-
console.error(`Unable to load questions for framework "${frameworkId}"`, error)
346+
console.error(`Unable to load questions for stack "${stackId}"`, error)
347347
setDynamicSteps([])
348-
setIsFrameworkFastTrackPromptVisible(false)
348+
setIsStackFastTrackPromptVisible(false)
349349
} finally {
350350
}
351351
}
@@ -361,7 +361,7 @@ export function InstructionsWizard({ onClose, selectedFileId }: InstructionsWiza
361361

362362
wizardSteps.forEach((step) => {
363363
step.questions.forEach((question) => {
364-
if (question.id === FRAMEWORK_QUESTION_ID) {
364+
if (question.id === STACK_QUESTION_ID) {
365365
return
366366
}
367367

@@ -390,7 +390,7 @@ export function InstructionsWizard({ onClose, selectedFileId }: InstructionsWiza
390390
setAutoFillNotice(null)
391391
}
392392

393-
setIsFrameworkFastTrackPromptVisible(false)
393+
setIsStackFastTrackPromptVisible(false)
394394

395395
const lastStepIndex = Math.max(wizardSteps.length - 1, 0)
396396
const lastStep = wizardSteps[lastStepIndex]
@@ -402,14 +402,14 @@ export function InstructionsWizard({ onClose, selectedFileId }: InstructionsWiza
402402
}
403403

404404
const beginStepByStepFlow = () => {
405-
const firstNonFrameworkIndex = wizardSteps.findIndex((step) => step.id !== FRAMEWORK_STEP_ID)
405+
const firstNonStackIndex = wizardSteps.findIndex((step) => step.id !== STACK_STEP_ID)
406406

407-
if (firstNonFrameworkIndex !== -1) {
408-
setCurrentStepIndex(firstNonFrameworkIndex)
407+
if (firstNonStackIndex !== -1) {
408+
setCurrentStepIndex(firstNonStackIndex)
409409
setCurrentQuestionIndex(0)
410410
}
411411

412-
setIsFrameworkFastTrackPromptVisible(false)
412+
setIsStackFastTrackPromptVisible(false)
413413
setIsComplete(false)
414414
setAutoFillNotice(null)
415415
}
@@ -471,11 +471,11 @@ export function InstructionsWizard({ onClose, selectedFileId }: InstructionsWiza
471471

472472
clearAutoFilledFlag(question.id)
473473

474-
const isFrameworkQuestion = question.id === FRAMEWORK_QUESTION_ID
474+
const isStackQuestion = question.id === STACK_QUESTION_ID
475475

476476
const shouldAutoAdvance =
477477
!skipAutoAdvance &&
478-
!isFrameworkQuestion &&
478+
!isStackQuestion &&
479479
((question.allowMultiple && Array.isArray(nextValue) && nextValue.length > 0 && didAddSelection) ||
480480
(!question.allowMultiple && nextValue !== undefined && nextValue !== null && didAddSelection))
481481

@@ -485,12 +485,12 @@ export function InstructionsWizard({ onClose, selectedFileId }: InstructionsWiza
485485
}, 0)
486486
}
487487

488-
if (isFrameworkQuestion) {
488+
if (isStackQuestion) {
489489
if (nextValue === answer.value) {
490-
await loadFrameworkQuestions(answer.value, answer.label)
490+
await loadStackQuestions(answer.value, answer.label)
491491
} else {
492492
setDynamicSteps([])
493-
setIsFrameworkFastTrackPromptVisible(false)
493+
setIsStackFastTrackPromptVisible(false)
494494
}
495495
}
496496
}
@@ -521,10 +521,10 @@ export function InstructionsWizard({ onClose, selectedFileId }: InstructionsWiza
521521

522522
clearAutoFilledFlag(currentQuestion.id)
523523

524-
const isFrameworkQuestion = currentQuestion.id === FRAMEWORK_QUESTION_ID
524+
const isStackQuestion = currentQuestion.id === STACK_QUESTION_ID
525525

526-
if (isFrameworkQuestion) {
527-
await loadFrameworkQuestions(defaultAnswer.value, defaultAnswer.label)
526+
if (isStackQuestion) {
527+
await loadStackQuestions(defaultAnswer.value, defaultAnswer.label)
528528
return
529529
}
530530

@@ -540,7 +540,7 @@ export function InstructionsWizard({ onClose, selectedFileId }: InstructionsWiza
540540
setIsComplete(false)
541541
setGeneratedFile(null)
542542
setIsGenerating(false)
543-
setIsFrameworkFastTrackPromptVisible(false)
543+
setIsStackFastTrackPromptVisible(false)
544544
setAutoFilledQuestionMap({})
545545
setAutoFillNotice(null)
546546
}
@@ -609,14 +609,14 @@ export function InstructionsWizard({ onClose, selectedFileId }: InstructionsWiza
609609

610610
console.log("Template combination data:", {
611611
outputFile: questionsAndAnswers.outputFile,
612-
framework: questionsAndAnswers.frameworkSelection,
612+
stack: questionsAndAnswers.stackSelection,
613613
})
614614

615-
const frameworkSegment = questionsAndAnswers.frameworkSelection ?? "general"
615+
const stackSegment = questionsAndAnswers.stackSelection ?? "general"
616616
const fileConfig = fileOptions.find((file) => file.id === outputFileId)
617617

618618
const result = await generateInstructions({
619-
frameworkSegment,
619+
stackSegment,
620620
outputFileId,
621621
responses: questionsAndAnswers,
622622
fileFormat: fileConfig?.format,
@@ -651,8 +651,8 @@ export function InstructionsWizard({ onClose, selectedFileId }: InstructionsWiza
651651
: undefined
652652
const showChangeFile = Boolean(onClose && selectedFile)
653653

654-
const topButtonLabel = showFrameworkPivot ? "Choose a different network" : "Start Over"
655-
const topButtonHandler = showFrameworkPivot ? () => goToPrevious() : () => requestResetWizard()
654+
const topButtonLabel = showStackPivot ? "Choose a different stack" : "Start Over"
655+
const topButtonHandler = showStackPivot ? () => goToPrevious() : () => requestResetWizard()
656656

657657
const wizardLayout = (
658658
<div className="mx-auto flex w-full max-w-4xl flex-col gap-6">
@@ -682,7 +682,7 @@ export function InstructionsWizard({ onClose, selectedFileId }: InstructionsWiza
682682
</section>
683683
) : null}
684684

685-
{showFrameworkPivot ? (
685+
{showStackPivot ? (
686686
<section className="rounded-3xl border border-border/80 bg-card/95 p-6 shadow-lg">
687687
<div className="flex flex-col gap-6">
688688
<div className="space-y-4">
Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
11
[
22
{
3-
"id": "frameworkSelection",
4-
"question": "Which framework are you working with?",
5-
"responseKey": "frameworkSelection",
3+
"id": "stackSelection",
4+
"question": "Which stack are you working with?",
5+
"responseKey": "stackSelection",
66
"isReadOnlyOnSummary": true,
77
"answers": [
88
{
@@ -26,4 +26,4 @@
2626
}
2727
]
2828
}
29-
]
29+
]

file-templates/agents-template.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,7 @@ This guide provides conventions and best practices for building AI agent applica
66

77
## 1. Project Overview
88

9-
- Framework/Language: **{{frameworkSelection}}** / **{{language}}**
9+
- Stack/Language: **{{stackSelection}}** / **{{language}}**
1010
- Build tooling: **{{tooling}}**
1111
- Primary focus: **{{projectPriority}}**
1212

0 commit comments

Comments
 (0)