claudiovictors / frost
Framework PHP para apps mobile reais (iOS/Android) com sintaxe JSX-like sobre React Native.
Requires
- php: >=8.1
- nikic/php-parser: ^5.0
README
Framework PHP que permite escrever apps mobile reais (iOS/Android) usando sintaxe PHP com componentes estilo JSX, transpilando pra React Native.
<?php function App() { $count = useState(0); $styles = StyleSheet::create([ 'container' => ['flex' => 1, 'alignItems' => 'center', 'justifyContent' => 'center'], ]); return ( <View style={$styles->container}> <Text>Você clicou {$count} vezes</Text> <Button title="Clicar" onPress={fn() => setCount($count + 1)} /> </View> ); }
Isso vira JSX/JS de verdade, compilado pelo Metro e rodando com Hermes/JSC igual qualquer app React Native.
Pipeline
código PHP (.php, sintaxe JSX-like)
→ Lexer (tokeniza PHP + tags JSX-like)
→ Parser (tokens → AST)
→ Transpiler (AST → string JS/JSX válida)
→ ImportInjector (auto-import de componentes RN e hooks usados)
→ CLI (`frost build` / `frost dev`)
→ bundler do React Native (Metro) + Babel
→ engine JS (Hermes/JSC) + bridge nativo → app iOS/Android
Instalação
O Frost é o framework. O app que você constrói com ele é um projeto separado (ver seção "Criando um app" abaixo).
composer require claudiovictors/frost
O que já funciona
- Function components com JSX aninhado (qualquer componente do React Native)
useState— vira destructuring[x, setX]automaticamenteStyleSheet::create([...])if/elseif/elseforeach ($x as $v)eforeach ($x as $k => $v)- Múltiplos componentes em arquivos separados, importando um no outro
(
use App\Componentes\Header;) async function,await,try/catch/finally— chamadas de API- Auto-import de componentes React Native e hooks usados no arquivo
O que ainda não existe (v0.1)
- Classes,
for/while/switch/match - Navegação entre telas (React Navigation)
- Context/Providers
- Resolução de namespace/PSR-4 de verdade pro
use(hoje é convenção de nome de arquivo — o último segmento do namespace precisa bater com o nome do.php)
Criando um app
O framework e o app consumidor vivem em projetos/pastas separados.
-
Cria um projeto React Native de verdade (o Frost não gera as pastas nativas
android//ios/— verstubs/rn-bridge-template/README.mdpra entender por quê):npx create-expo-app MeuApp --template blank # ou: npx @react-native-community/cli init MeuApp -
Copia os arquivos de
stubs/rn-bridge-template/(do pacote Frost instalado via Composer, emvendor/frost/framework/stubs/rn-bridge-template/) por cima do seu projeto RN — são oApp.jsde ponte, config do Babel/Metro e a pastasrc/generated/onde o Frost escreve o output. -
Cria seu código-fonte
.phpnuma pasta separada (ex:app/App.php) e umfrost.config.phpapontando pra ela (verfrost.config.example.phpneste repositório). -
Compila e observa mudanças:
vendor/bin/frost build # compila uma vez vendor/bin/frost dev # observa e recompila automaticamente
-
Roda o app normalmente (
npx expo startounpx react-native run-android).
Estrutura do framework
src/
├── Lexer/ tokeniza PHP + tags JSX-like
├── Parser/ tokens → AST (recursive-descent, escrito à mão)
├── Ast/ nós de AST: statements, JSX
├── Expr/ nós de AST: expressões
├── Transpiler/ AST → string JS/JSX
├── Components/ registro de componentes RN/hooks, auto-import
└── Cli/ comandos `build` e `dev`
stubs/
└── rn-bridge-template/ projeto RN mínimo que roda o output do Frost
Licença
MIT