hideyukimori / nene2
PHP micro-framework: JSON APIs first, minimal server HTML, easy React/SPA integration, structure friendly to AI tooling.
Requires
- php: >=8.4.1 <9.0
- monolog/monolog: ^3.0
- nyholm/psr7: ^1.8
- nyholm/psr7-server: ^1.1
- psr/container: ^2.0
- psr/http-server-handler: ^1.0
- psr/http-server-middleware: ^1.0
- psr/log: ^3.0
- vlucas/phpdotenv: ^5.6
Requires (Dev)
- friendsofphp/php-cs-fixer: ^3.95
- phpstan/phpstan: ^2.1
- phpunit/phpunit: ^13.1
- robmorgan/phinx: ^0.16.11
- symfony/yaml: ^8.0
Suggests
- symfony/yaml: Required to run validate-mcp-tools.php from a consumer project (add to your require-dev)
- dev-main
- v1.5.53
- v1.5.52
- v1.5.51
- v1.5.50
- v1.5.49
- v1.5.48
- v1.5.47
- v1.5.46
- v1.5.45
- v1.5.44
- v1.5.43
- v1.5.42
- v1.5.41
- v1.5.40
- v1.5.39
- v1.5.38
- v1.5.37
- v1.5.36
- v1.5.35
- v1.5.34
- v1.5.33
- v1.5.32
- v1.5.31
- v1.5.30
- v1.5.29
- v1.5.28
- v1.5.27
- v1.5.26
- v1.5.25
- v1.5.24
- v1.5.23
- v1.5.22
- v1.5.21
- v1.5.20
- v1.5.19
- v1.5.18
- v1.5.17
- v1.5.16
- v1.5.15
- v1.5.14
- v1.5.13
- v1.5.12
- v1.5.11
- v1.5.10
- v1.5.9
- v1.5.8
- v1.5.7
- v1.5.6
- v1.5.5
- v1.5.4
- v1.5.3
- v1.5.2
- v1.5.1
- v1.5.0
- v1.4.2
- v1.4.1
- v1.4.0
- v1.3.0
- v1.2.0
- v1.1.0
- v1.0.0
- v0.8.0
- v0.7.0
- v0.6.0
- v0.5.0
- v0.4.0
- v0.3.0
- v0.2.0
- v0.1.3
- v0.1.2
- v0.1.1
- v0.1.0
- dev-docs/740-ft119-circuit-breaker
- dev-docs/738-ft118-signed-urls
- dev-docs/736-ft117-api-key-management
- dev-docs/734-ft116-job-queue
- dev-docs/732-ft115-api-versioning
- dev-docs/730-ft114-audit-trail
- dev-docs/728-refresh-token-rotation
- dev-docs/726-multi-tenant-isolation
- dev-docs/724-rbac-howto
- dev-docs/722-jwt-authentication-howto
- dev-docs/720-password-hashing-howto
- dev-docs/718-soft-delete
- dev-docs/716-rate-limiting
- dev-docs/714-etag-conditional-requests
- dev-feat/712-ft105-optimistic-locking
- dev-feat/710-ft104-webhook-signature
- dev-feat/708-ft103-mass-assignment
- dev-feat/706-ft102-transactions
- dev-feat/704-ft101-nested-json-validation
- dev-feat/702-ft100-pagination
- dev-feat/699-700-ft99-csrf-idempotency
- dev-feat/697-ft98-file-upload
- dev-chore/695-update-current-md-and-gitignore
- dev-feat/691-692-693-ft97-sql-injection
- dev-docs/689-ft96-content-negotiation
- dev-feat/686-687-ft95-tz-querystring
- dev-docs/684-ft94-bearer-auth-howto
- dev-feat/681-682-ft93-unicode
- dev-docs/679-booking-concurrency-howto
- dev-docs/677-idor-ownership-howto
- dev-feat/674-675-conditional-write-helper
- dev-feat/671-672-sqlite-fk-json-array-docs
- dev-feat/669-database-constraint-exception
- dev-docs/667-field-trial-75
- dev-docs/665-field-trial-74
- dev-docs/663-field-trial-73
- dev-docs/661-field-trial-72
- dev-docs/659-field-trial-71
- dev-docs/657-field-trial-70
- dev-docs/655-field-trial-69
- dev-docs/653-ft68-approval
- dev-docs/651-ft67-reservation
- dev-feat/649-router-static-priority
- dev-docs/647-ft63-65-reports
- dev-feat/645-json-response-factory-create-list
- dev-docs/643-ft58-cqrslog
- dev-docs/641-ft57-ftslog
- dev-docs/639-ft56-etaglog
- dev-feat/637-conditional-get-helper
- dev-docs/635-ft55-idempotencylog
- dev-docs/633-ft54-optimisticlog
- dev-docs/631-ft53-ratelog
- dev-docs/629-ft52-bulkupdatelog
- dev-docs/628-ft51-commentlog
- dev-docs/627-ft50-notificationlog
- dev-docs/626-ft49-softdelete
- dev-feat/624-router-params-attribute-howto
- dev-feat/621-622-querystring-array-having-howto
- dev-docs/619-ft46-ratelimitlog
- dev-docs/617-ft45-eventstore
- dev-docs/615-ft44-moneylog
- dev-docs/613-ft43-batchlog
- dev-docs/611-ft41-ft42-field-trials
- dev-docs/609-optional-body-action-endpoints
- dev-docs/607-fts5-howto
- dev-docs/604-605-ft34-ft35-reports
- dev-feat/602-603-ft33-frictions
- dev-feat/600-ft32-having-cast
- dev-docs/598-ft31-fts5-howto
- dev-fix/596-ft30-sqlite-foreign-keys
- dev-feat/593-594-ft29-timelog
- dev-feat/591-ft28-bulk-validation-docs
- dev-feat/589-ft27-action-endpoints
- dev-feat/586-587-ft26-frictions
- dev-feat/584-query-string-comma-separated
- dev-feat/582-ft24-cors-preflight-docs
- dev-feat/578-579-580-ft23-frictions
- dev-feat/574-576-ft22-frictions
- dev-feat/570-572-ft21-frictions
- dev-docs/568-field-trial-21
- dev-chore/ft20-complete
- dev-docs/562-565-ft20-frictions
- dev-docs/560-field-trial-20
- dev-chore/559-ft19-friction-complete
- dev-feat/555-556-557-ft19-frictions
- dev-docs/553-field-trial-19
- dev-chore/552-release-v1.5.2
- dev-docs/549-use-transactions-howto
- dev-fix/547-548-requestmaxbodybytes-unionpath
- dev-docs/545-field-trial-18
- dev-chore/v1.5.1-release
- dev-docs/542-cs-fixer-risky-docs
- dev-feat/540-factory-method-prefix-params
- dev-docs/538-field-trial-17
- dev-docs/536-v1.5.0-docs-update
- dev-fix/532-533-cors-maxage-head-test
- dev-fix/528-529-530-531-size-auth-cors
- dev-docs/488-490-field-trial-15-16
- dev-fix/520-521-522-cors-throttle-ci
- dev-fix/517-518-519-openapi-apikey-json
- dev-fix/514-515-516-error-logging-csp-cors
- dev-fix/512-513-head-mcp-patch
- dev-docs/505-506-507-p3-p4-docs
- dev-test/503-504-p3-tests-and-cache
- dev-feat/499-500-501-502-p2-api-clarity
- dev-fix/496-497-498-p1-security
- dev-chore/v1.5.0-release
- dev-docs/493-ft15-friction-fixes
- dev-test/489-mcp-layer
- dev-test/486-view-layer-tests
- dev-refactor/463-example-service-provider
- dev-docs/462-469-457-auth-attrs-phpstan-mn-howto
- dev-feat/461-482-apikey-path-prefix-method-filter
- dev-docs/ft14-milestone
- dev-feat/466-composite-auth-middleware
- dev-docs/474-475-ft13-mysql-docs
- dev-docs/ft13-milestone
- dev-docs/ft12c-complete
- dev-feat/467-468-bearer-prefix-match-and-local-verifier-public
- dev-docs/ft12b-complete-ft12c-milestone
- dev-fix/459-460-mcp-validator-consumer-project
- dev-docs/ft12a-complete-ft12b-milestone
- dev-docs/ft12-milestones
- dev-feat/openapi-prominence
- dev-feat/llms-txt
- dev-docs/444-add-jwt-authentication-howto
- dev-docs/443-claude-md-dev-vs-installed
- dev-feat/442-token-issuer-interface
- dev-feat/441-runtime-factory-middleware-interface
- dev-feat/440-bearer-middleware-excluded-paths
- dev-chore/ft11-followup-issues
- dev-docs/434-ft11-planning
- dev-docs/432-sqlite-schema-init
- dev-feat/phase-61-ft10-features
- dev-feat/phase-60-ft10-followup
- dev-docs/field-trial-10-hoplog
- dev-chore/420-changelog-framework-info-version
- dev-docs/417-418-framework-info-version-phpdoc
- dev-chore/416-vitepress-badge-v1.4.0
- dev-chore/415-v1.4.0-release
- dev-docs/413-post-409-doc-sync
- dev-chore/412-changelog-update
- dev-feat/409-problem-details-base-url
- dev-chore/410-problem-details-domain-resolved
- dev-chore/407-post-v1.3-review-docs
- dev-chore/402-todo-398-400
- dev-docs/400-locale-env-roadmap-fix
- dev-docs/398-v1.1-milestone-readme-fix
- dev-chore/396-todo-394
- dev-docs/394-openapi-readme-accuracy-fix
- dev-chore/392-trim-current-todo
- dev-chore/390-todo-388-cleanup
- dev-chore/388-post-v1-stale-cleanup
- dev-chore/386-todo-384-locale-sync
- dev-docs/384-locale-http-endpoints-413-sync
- dev-chore/382-todo-phase57
- dev-fix/380-i18n-link-fallback
- dev-chore/378-todo-371-372
- dev-chore/376-field-trial-9-packagist-done
- dev-docs/372-release-checklist-github-release
- dev-fix/371-phpstan-memory-limit
- dev-docs/370-field-trial-9
- dev-chore/368-phase55-dependabot-done
- dev-dependabot/npm_and_yarn/frontend/vite-8.0.13
- dev-docs/366-vitepress-v1.3-pagination
- dev-chore/364-v1.3.0-release
- dev-feat/362-openapi-to-md
- dev-feat/360-pagination-query-parser
- dev-docs/358-vitepress-v1.2-howto
- dev-chore/356-v1.2.0-release
- dev-fix/354-json-body-parser
- dev-fix/352-throttle-test-server-params
- dev-chore/350-v1.1.0-release
- dev-feat/348-rate-limiting
- dev-feat/346-health-check-interface
- dev-docs/344-v1.1-roadmap
- dev-chore/v1.0.0-release
- dev-chore/340-v1.0-readiness
- dev-chore/v0.8.0-release
- dev-chore/337-v1.0-gaps
- dev-docs/334-phase40-followup
- dev-docs/334-adr-0009-v1.0-public-api-scope
- dev-dependabot/npm_and_yarn/frontend/vitejs/plugin-react-6.0.2
- dev-dependabot/npm_and_yarn/frontend/eslint-10.4.0
- dev-dependabot/npm_and_yarn/frontend/typescript-eslint-8.59.3
- dev-dependabot/github_actions/actions/deploy-pages-5
- dev-dependabot/github_actions/actions/upload-pages-artifact-5
- dev-dependabot/github_actions/actions/cache-5
- dev-dependabot/composer/friendsofphp/php-cs-fixer-3.95.2
- dev-dependabot/composer/symfony/yaml-8.0.11
- dev-dependabot/composer/phpunit/phpunit-13.1.10
- dev-docs/322-vitepress-reference-section
- dev-feat/320-react-component-tests
- dev-feat/318-vitest-frontend-api-tests
- dev-fix/316-test-symmetry-schema-gaps
- dev-feat/314-frontend-tag
- dev-test/312-pdo-tag-mysql
- dev-test/304-tag-update-delete-coverage
- dev-docs/tag-howto-fix
- dev-docs/306-field-trial-7
- dev-feat/304-tag-crud-completion
- dev-docs/302-phase34-v060-release
- dev-feat/300-mcp-write-auth-guard
- dev-refactor/298-slim-application-factory
- dev-feat/296-ft6-followup
- dev-docs/291-phase32-field-trial-6
- dev-docs/289-phase31-auth-checklist
- dev-feat/287-phase30-openapi-bearer
- dev-chore/284-phase29-tag-done
- dev-chore/284-phase29-v0.5.0-release
- dev-feat/282-phase28-auth-expansion
- dev-feat/280-phase27-frontend-starter
- dev-docs/278-phase26-production-deploy
- dev-feat/276-phase25-tag-entity
- dev-dependabot/npm_and_yarn/frontend/react-dom-19.2.6
- dev-docs/274-phase24-explanation
- dev-dependabot/github_actions/actions/checkout-6
- dev-dependabot/github_actions/actions/setup-node-6
- dev-ci/272-phase23-ci-hardening
- dev-docs/270-roadmap-phase23
- dev-ci/268-github-pages
- dev-feat/266-translate-reference
- dev-fix/264-i18n-404
- dev-feat/262-dark-mode-rich-design
- dev-feat/260-i18n-docs
- dev-feat/258-vitepress-docs-site
- dev-docs/256-docs-index
- dev-docs/253-254-howto-routes-and-db
- dev-docs/251-tutorial-first-api
- dev-docs/249-phase22-diataxis-docs
- dev-docs/245-246-mcp-write-db-preconditions
- dev-docs/244-field-trial-5-report
- dev-docs/242-phase21-field-trial-5
- dev-chore/240-v0.4.0-release
- dev-feat/236-route-registrars
- dev-docs/234-235-path-params-and-composer-require
- dev-docs/233-phase20-packagist-field-trial
- dev-feat/228-mcp-write-tools
- dev-dependabot/npm_and_yarn/frontend/react-19.2.6
- dev-dependabot/npm_and_yarn/frontend/vite-8.0.11
- dev-dependabot/composer/symfony/yaml-8.0.10
- dev-docs/166-field-trial-sandbox-links
- dev-chore/164-field-trial-done
- dev-chore/162-mark-field-trial-template-done
- dev-docs/160-field-trial-report-template
This package is auto-updated.
Last update: 2026-05-21 05:35:42 UTC
README
PHP micro-framework: JSON APIs first, minimal server HTML, easy React starter integration, structure friendly to AI tooling.
OpenAPI contract — machine-readable API spec (OpenAPI 3.1). Live Swagger UI at http://localhost:8080/docs/ after docker compose up -d app.
NENE2 is a small, modern PHP framework foundation designed for projects that want to ship JSON APIs quickly, keep server-rendered HTML thin, and add a React frontend starter without turning the backend into frontend build glue.
The v1.x foundation covers full Note/Tag CRUD, Bearer JWT auth, pagination helpers, and a six-language VitePress documentation site, with opt-in rate limiting and database health checks as production-ready opt-in features. A maintainer can clone the repository, run a local API, share an OpenAPI contract, expose safe MCP tools through the API boundary, and verify database behavior in Docker Compose.
Theme
- API first: define behavior through clear HTTP boundaries and OpenAPI contracts.
- Simple HTML: keep server HTML minimal, predictable, and easy to replace with SPA shells.
- Frontend ready: provide a React + TypeScript starter direction while keeping the frontend layer replaceable.
- AI readable: prefer explicit directories, small classes, typed boundaries, and documented decisions.
- LLM delivery ready: keep API, MCP, auth, database, and handoff docs aligned for small client-style projects.
- Modern PHP: use strict types, PSR-oriented style, dependency injection, automated tests, and static analysis.
Current Capabilities
The foundation currently includes:
- PSR-7 / PSR-15 / PSR-17 HTTP runtime with explicit routing and middleware.
- OpenAPI contract, Swagger UI, and runtime contract tests for shipped JSON endpoints.
- RFC 9457 Problem Details error responses.
- Typed app and database configuration through
.envloading boundaries. - PSR-11 dependency injection with explicit runtime service wiring.
- PDO connection, query executor, transaction manager, SQLite tests, and opt-in MySQL verification through Docker Compose.
- Bearer JWT middleware with allowlist, blocklist, and prefix path options;
CompositeAuthMiddlewarefor three-tier access models (public / Bearer / API key). - API-key middleware with path and method filters for machine-client endpoints.
- Server-rendered HTML via
NativePhpViewRendererandHtmlResponseFactory— thin HTML coexists with JSON API routes. - Local MCP server support for read/write tools aligned with OpenAPI, with an authentication guard on write operations.
- React + TypeScript + Vite starter kept optional and decoupled from backend runtime behavior.
Installation
NENE2 is available on Packagist.
The recommended way to start a new project is to clone the repository directly — it ships with Docker, .env.example, and all configuration you need out of the box:
git clone https://github.com/hideyukiMORI/NENE2.git my-project
cd my-project
If you want to use NENE2 as a Composer dependency in an existing project:
composer require hideyukimori/nene2
Quick Start
Build the PHP runtime, install dependencies, and run the standard backend checks:
cp .env.example .env docker compose build docker compose run --rm app composer install docker compose run --rm app composer check
Start the local web runtime:
docker compose up -d app
The web entry point is served from public_html/ at http://localhost:8080/.
Useful local URLs:
- API health:
http://localhost:8080/health - Example endpoint:
http://localhost:8080/examples/ping - OpenAPI:
http://localhost:8080/openapi.php - Swagger UI:
http://localhost:8080/docs/
Run optional real MySQL verification when database adapter behavior should be checked against a service database:
docker compose up -d mysql docker compose run --rm app composer test:database:mysql
Domain Layer Example
src/Example/Note/ and src/Example/Tag/ are reference implementations — they demonstrate how to use the framework, but are not part of the public API stability guarantee (see ADR 0009). Copy and adapt the patterns into your own application; do not import these classes as library dependencies.
src/Example/Note/ implements a full Note CRUD with:
| Layer | File(s) |
|---|---|
| Route + handler | GetNoteByIdHandler, CreateNoteHandler, UpdateNoteHandler, DeleteNoteHandler, ListNotesHandler |
| Use case (domain) | GetNoteByIdUseCase, CreateNoteUseCase, UpdateNoteUseCase, DeleteNoteUseCase, ListNotesUseCase |
| Repository interface | NoteRepositoryInterface |
| PDO adapter | PdoNoteRepository |
| Exception mapping | NoteNotFoundException → NoteNotFoundExceptionHandler → 404 Problem Details |
| OpenAPI | docs/openapi/openapi.yaml — GET/POST/PUT/DELETE /examples/notes paths |
| Tests | tests/Example/Note/ — unit, HTTP-level, PDO integration |
All Note endpoints are live at http://localhost:8080/examples/notes after docker compose up -d app.
Development Principles
NENE2 optimizes for fast, calm development. The codebase should be easy for a solo developer, a team, or an AI agent to understand without hidden conventions.
- Keep domain and use-case code decoupled from HTTP, database, template, and CLI details.
- Use PSR-7 / PSR-15 / PSR-17 as the HTTP runtime direction.
- Use PSR-11 as the DI boundary, with explicit wiring first.
- Use typed config objects at runtime; keep
.envat the loading boundary. - Make behavior testable before adding framework magic.
- Treat OpenAPI as the public API contract and keep MCP integrations behind the same API boundary.
- Keep template engines optional; server HTML should stay thin and replaceable.
- Prefer small, boring primitives over clever abstractions.
- Record workflow, roadmap, and implementation decisions in
docs/rather than only in chat.
Repository Layout
NENE2 uses a single repository with Composer at the root, PHP framework code in src/, tests in tests/, a web document root in public_html/, and optional React + TypeScript frontend source in frontend/.
.
├── composer.json
├── src/ # NENE2 framework core
│ ├── Auth/
│ ├── Config/
│ ├── Database/
│ ├── DependencyInjection/
│ ├── Error/
│ ├── Http/
│ ├── Log/
│ ├── Mcp/
│ ├── Middleware/
│ ├── Routing/
│ ├── Validation/
│ ├── View/
│ ├── Example/Note/ # canonical domain layer example (full CRUD)
│ └── Example/Tag/ # second entity example
├── tests/ # PHPUnit / architecture / contract tests
├── config/ # framework default config or examples
├── database/ # migrations, seeds, and schema docs
├── templates/ # native PHP templates and thin server HTML source
├── public_html/ # web document root
│ └── assets/ # built frontend assets
├── frontend/ # React/TypeScript/Vite source
│ └── src/
├── docs/
├── LICENSE
└── README.md
See docs/development/project-layout.md for the design details and placement rules.
Development Commands
For a full step-by-step walkthrough from clone to running API, see docs/development/setup.md.
NENE2 targets PHP >=8.4.1 <9.0. Docker is the standard development runtime, so the host OS does not need to provide that PHP version.
docker compose run --rm app composer check
Composer lives at the repository root and provides the first backend verification commands:
composer validate
composer test
composer analyse
composer check
composer test:database
composer test:database:mysql
See docs/development/php-runtime.md and docs/development/docker.md for runtime and tooling details.
NENE2's quality baseline includes PHP-CS-Fixer for backend style checks and npm, ESLint, TypeScript, and Prettier for the React frontend starter. The frontend starter targets active Node.js LTS, commits package-lock.json, and keeps dependencies modern through update automation. Framework public APIs should use PHPDoc or TSDoc where comments explain contracts or extension rules. See docs/development/quality-tools.md, docs/development/frontend-integration.md, and docs/development/documentation-comments.md.
How-to guides
Step-by-step recipes for common tasks:
- Add a custom route
- Add a database-backed endpoint
- Use database transactions
- Add a second entity
- Add pagination
- Add JWT authentication
- Add rate limiting
- Add a health check
- Add an HTML view
- Add MCP tools
- Deploy to production
Delivery Starter Docs
Start with these docs when adapting NENE2 for a small client-style API:
- Direction:
docs/integrations/llm-delivery-starter.md - Client project start guide:
docs/development/client-project-start.md - Endpoint workflow:
docs/development/endpoint-scaffold.md - Local MCP server:
docs/integrations/local-mcp-server.md - Local MCP client configuration:
docs/integrations/local-mcp-client-configuration.md - MCP tool policy:
docs/integrations/mcp-tools.md - Authentication boundary:
docs/development/authentication-boundary.md - Machine-client smoke workflow:
docs/development/machine-client-smoke.md - Database test strategy:
docs/development/test-database-strategy.md - Patch release policy:
docs/development/release-v0.1.x-policy.md
Public field trial reference (optional): hideyukiMORI/sakura-exhibition-nene2-field-trial — client-style demo forked from v0.1.1 with exhibition-shaped read-only APIs, OpenAPI, tests, local MCP, and field-trial reports. Not affiliated with any real event; see that repository’s README.md.
Project Workflow
NENE2 uses GitHub Issues as the source of work and local Markdown files as the project memory.
- Create or reuse a focused GitHub Issue.
- Create an Issue-numbered branch from
main, such asdocs/1-initial-governance. - Update code and docs together, keeping the change small.
- Commit with Conventional Commits and include the Issue number.
- Push, open a PR, merge after checks, and return local
mainto a clean state.
See docs/CONTRIBUTING.md, docs/workflow.md, and AGENTS.md before changing the project.
AI / LLM Integration
NENE2 is designed to be AI-readable and usable as a tool by AI agents.
llms.txt— machine-readable project summary for LLM crawlers (llmstxt.org standard).- Smithery — NENE2 MCP server listed in the Smithery registry (
smithery.yaml). - AGENTS.md — entry point for AI agents working in this repository.
- OpenAPI contract —
GET /openapi.phpordocs/openapi/openapi.yaml— the authoritative API contract for LLM tool use. - Local MCP server —
composer mcpvalidates the MCP tool catalog;composer run local-mcp-serverstarts the local server. - Field trial reports — real-world AI implementation records: hoplog (FT10), tasklog (FT11).
License
NENE2 is released under the MIT License.