File size: 4,475 Bytes
a9446d7
010bc6c
a9446d7
 
 
 
 
010bc6c
 
a9446d7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
010bc6c
 
a9446d7
 
010bc6c
a9446d7
010bc6c
a9446d7
 
 
010bc6c
 
 
a9446d7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
010bc6c
a9446d7
 
 
 
 
 
 
 
 
 
 
 
 
010bc6c
 
a9446d7
 
 
 
 
 
 
010bc6c
 
a9446d7
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
010bc6c
 
a9446d7
010bc6c
 
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
import { FormEvent, useMemo, useState } from 'react';

type SpecPreview = {
  intent: string;
  mode: 'part' | 'assembly' | 'sketch';
  output: '3d_solid' | 'surface' | '2d_vector' | '1d_path';
  notes: string[];
};

const defaultPrompt = 'A modular steel bracket with 4 bolt holes and a cable channel';

const features = [
  {
    title: 'Prompt to geometry in one flow',
    body: 'Natural-language input, generated build123d logic, and export-ready CAD artifacts in one run.'
  },
  {
    title: 'Export-first workflow',
    body: 'STEP and STL for fabrication, DXF for linework and laser workflows, with lineage per run.'
  },
  {
    title: 'Enterprise controls ready',
    body: 'Structured API boundaries, auth gates, observability, and path to RBAC and tenant isolation.'
  }
];

const steps = [
  'Describe the object in plain language.',
  'NaturalCAD resolves intent into CAD-safe generation logic.',
  'Review the model, then download STEP/STL/DXF artifacts.'
];

function inferSpec(prompt: string): SpecPreview {
  const text = prompt.toLowerCase();
  const is2d = /dxf|profile|laser|plate|outline/.test(text);
  const is1d = /route|centerline|path|wire/.test(text);
  const output = is1d ? '1d_path' : is2d ? '2d_vector' : '3d_solid';

  return {
    intent: prompt.trim() || defaultPrompt,
    mode: output === '3d_solid' ? 'part' : 'sketch',
    output,
    notes: [
      'Dimension constraints inferred from prompt language.',
      'Geometry kept bounded for stable generation latency.',
      'Artifacts prepared for downstream CAD handoff.'
    ]
  };
}

export default function App() {
  const [prompt, setPrompt] = useState(defaultPrompt);
  const [submittedPrompt, setSubmittedPrompt] = useState(defaultPrompt);

  const spec = useMemo(() => inferSpec(submittedPrompt), [submittedPrompt]);

  const handleSubmit = (event: FormEvent) => {
    event.preventDefault();
    setSubmittedPrompt(prompt);
  };

  return (
    <main className="site-shell">
      <header className="topbar">
        <div className="brand">NaturalCAD</div>
        <nav>
          <a href="#product">Product</a>
          <a href="#workflow">Workflow</a>
          <a href="#pilot">Pilot</a>
        </nav>
      </header>

      <section className="hero" id="product">
        <div>
          <p className="eyebrow">NaturalCAD • Website Prototype v0</p>
          <h1>Design with words. Ship real CAD artifacts.</h1>
          <p className="hero-copy">
            This is a first-pass front end for your domain launch. It positions NaturalCAD as a product,
            not just a demo, while keeping a live prompt-to-spec interaction on the page.
          </p>
          <div className="cta-row">
            <a className="btn btn-primary" href="https://huggingface.co/spaces/kNOWare/naturalcad" target="_blank" rel="noreferrer">
              Open current Space
            </a>
            <a className="btn btn-ghost" href="#pilot">Request pilot access</a>
          </div>
        </div>

        <form className="spec-card" onSubmit={handleSubmit}>
          <label htmlFor="prompt">Try a concept prompt</label>
          <textarea
            id="prompt"
            value={prompt}
            onChange={(event) => setPrompt(event.target.value)}
            rows={5}
          />
          <button className="btn btn-primary" type="submit">Preview inferred spec</button>

          <pre>{JSON.stringify(spec, null, 2)}</pre>
        </form>
      </section>

      <section className="feature-grid" aria-label="key features">
        {features.map((feature) => (
          <article key={feature.title} className="feature-card">
            <h2>{feature.title}</h2>
            <p>{feature.body}</p>
          </article>
        ))}
      </section>

      <section className="workflow" id="workflow">
        <h2>How the production flow lands</h2>
        <ol>
          {steps.map((step) => (
            <li key={step}>{step}</li>
          ))}
        </ol>
      </section>

      <section className="pilot" id="pilot">
        <h2>Enterprise pilot</h2>
        <p>
          Start with one team, one artifact lane, and traceability from prompt to export. Then scale by
          domain, policy, and workload.
        </p>
        <div className="pilot-tags">
          <span>API-first</span>
          <span>Audit trail</span>
          <span>STEP/STL/DXF</span>
          <span>Private deployment path</span>
        </div>
      </section>
    </main>
  );
}