Skip to content

Instantly share code, notes, and snippets.

@llandsmeer
Created August 4, 2025 07:12
Show Gist options
  • Save llandsmeer/73da84e90677fd8a533c0ea415e012a6 to your computer and use it in GitHub Desktop.
Save llandsmeer/73da84e90677fd8a533c0ea415e012a6 to your computer and use it in GitHub Desktop.
Typescript preact boilerplate
npx esbuild main.tsx --bundle --format=esm --outfile=dist/main.js --jsx=automatic --jsx-import-source=preact
npm init
npm install @preact/signals
npm install -g typescript-language-server
npm install --save-dev typescript
npm install --save-dev esbuild
npm install preact
import { h, render, createContext } from 'preact';
import { signal, computed, Signal } from '@preact/signals';
import { useContext, useState } from 'preact/hooks';
interface Todo {
text: string
completed: boolean
}
class AppState {
todos: Signal<Todo[]> = signal([])
completed: Signal<number> = computed(() => {
return this.todos.value.filter(todo => todo.completed).length;
});
insert(text: string) {
console.log(text)
this.todos.value = [...this.todos.value, { text: text, completed: true }]
console.log(this.todos.value)
}
toggle(todo: Todo) {
this.todos.value = this.todos.value.map(t =>
t === todo ? { ...todo, completed: !todo.completed } : t
)
}
}
const AppStateContext = createContext(undefined);
function appState() { return useContext(AppStateContext) }
function Adder() {
const app = appState()
const [value, setValue] = useState('');
return <div>
<input
type="text"
value={value}
onInput={e => setValue(e.currentTarget.value)}
placeholder="Type here"
/>
<button onClick={() => {app.insert(value); setValue('')}}>Test</button>
</div>
}
function App() {
const app = appState()
return <p>
<b>{app.completed}</b>
<ul>
{app.todos.value.map((todo: Todo) => (
<li>{todo.text} {todo.completed ? 'V' : 'X'}
<button onClick={()=>app.toggle(todo)}>Toggle</button>
</li>
))}
</ul>
<Adder/>
</p>;
}
render(
<AppStateContext.Provider value={new AppState()}>
<App />
</AppStateContext.Provider>,
document.getElementById('app'));
{
"compilerOptions": {
"jsx": "react",
"jsxFactory": "h",
"jsxFragmentFactory": "Fragment",
"sourceMap": true
},
"include": ["main.tsx"]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment