Vertical Slice Specification
1. Purpose
This document defines the first end-to-end vertical slice of the Foodtruck Order application.
The purpose of this slice is not to implement meaningful foodtruck functionality. Its purpose is to prove that the project's fundamental technical path works as an integrated system:
PostgreSQL
↓
Backend data access
↓
Backend application/API
↓
HTTP/JSON
↓
React frontend
↓
Browser
The vertical slice must also establish the foundation for:
- automated testing,
- Docker-based local development,
- reproducible development,
- CI validation,
- project documentation,
- AI-assisted development.
The slice is intentionally trivial. Its value comes from proving the complete technical path with the smallest possible amount of business logic.
Once this slice is complete, future functionality can be implemented incrementally using the same vertical-slice approach.
2. Scope
2.1 Included
The first vertical slice includes:
- A PostgreSQL database.
- A minimal database schema containing a message.
- Backend database connectivity.
- Backend data-access logic.
- A backend API endpoint that retrieves the message.
- A React frontend that calls the API.
- A frontend view that displays the message.
- Automated tests at the appropriate testing levels.
- Docker-based local infrastructure.
- End-to-end verification through the real database.
- CI execution of the relevant automated checks.
- Documentation of how the system is developed and verified.
2.2 Explicitly excluded
The first vertical slice does not include:
- authentication or authorization,
- users,
- customers,
- orders,
- products,
- menus,
- payments,
- Surfboard payment or fiscal integration,
- Swish integration,
- QR ordering,
- kitchen displays,
- order status management,
- multi-device synchronization,
- real-time communication,
- WebSockets,
- Redis,
- production deployment,
- advanced logging infrastructure,
- analytics,
- statistics,
- queue prediction,
- business recommendations,
- complex domain logic,
- external APIs,
- sophisticated error handling,
- production-grade observability.
These features may be added in later vertical slices when they provide actual value.
Do not add infrastructure merely because a future feature may eventually require it.
3. Example Feature
The first slice uses a deliberately simple Message concept.
The database contains one message.
For example:
Hello from the database!
The backend exposes an API endpoint:
GET /api/message
The endpoint retrieves the message from PostgreSQL and returns it as JSON.
The frontend calls the endpoint and displays the returned message in the browser.
The final result should therefore be observable by a developer opening the application in a browser:
Hello from the database!
The important property is that the displayed text originates from PostgreSQL.
It must not be hard-coded into the frontend.
4. End-to-End Data Flow
The completed slice must implement the following flow:
┌─────────────┐
│ PostgreSQL │
│ │
│ Message row │
└──────┬──────┘
│
│ SQL / database driver
▼
┌─────────────────────┐
│ Backend │
│ │
│ Data access │
│ Application logic │
│ API endpoint │
└──────────┬──────────┘
│
│ HTTP / JSON
▼
┌─────────────────────┐
│ React frontend │
│ │
│ API client │
│ Page / component │
└──────────┬──────────┘
│
▼
┌─────────────────────┐
│ Browser │
│ │
│ Hello from the │
│ database! │
└─────────────────────┘
The implementation should follow the architectural boundaries defined in docs/architecture.md.
In particular:
- The frontend must not access PostgreSQL directly.
- The frontend must not contain database credentials.
- The API layer must not contain unnecessary database implementation details.
- Database-specific logic should remain in the backend data-access layer.
- The backend must be the authoritative source for retrieving the message.
5. Database Requirements
The database must be PostgreSQL.
The slice must contain a minimal schema capable of storing the message.
A possible conceptual model is:
Message
-------
id
text
The exact column names and data types should follow the conventions established during implementation.
The database schema must be reproducible.
A fresh database must be capable of being initialized from the repository without manually creating tables.
Database initialization must therefore use the project's migration or schema-management mechanism rather than undocumented manual SQL commands.
The initial message must also be created reproducibly.
The preferred approach is to use a deterministic seed or equivalent initialization mechanism appropriate to the selected database tooling.
The application must not depend on data that exists only in one developer's local database.
6. Backend Requirements
The backend must:
- Start successfully.
- Connect to PostgreSQL using configuration rather than hard-coded credentials.
- Retrieve the message from the database.
- Expose an HTTP endpoint for the frontend.
- Return the message as JSON.
- Handle the basic failure case where the database cannot be reached.
- Be testable independently from the frontend.
The API should follow a simple contract.
Conceptually:
GET /api/message
Successful response:
{
"message": "Hello from the database!"
}
The exact response structure may be adjusted during implementation if the project's API conventions require it. Once established, the contract should be documented and tested.
The backend must not return a hard-coded response merely to make the frontend work.
The successful response must ultimately originate from PostgreSQL.
7. Frontend Requirements
The frontend must:
- Start successfully.
- Render a page.
- Call the backend API.
- Read the returned JSON.
- Display the message returned by the backend.
- Provide a basic loading state where appropriate.
- Provide a basic error state where appropriate.
The message must not be hard-coded into the frontend as the source of the displayed value.
For example, this is valid conceptually:
Frontend
↓
GET /api/message
↓
Backend
↓
PostgreSQL
↓
"Hello from the database!"
This is not sufficient:
Frontend
↓
"Hello from the database!"
The frontend should remain intentionally simple. The goal is to prove the integration path, not to establish a complete UI design system.
8. API Contract
The API contract must be explicit.
At minimum, the project should document:
- endpoint,
- HTTP method,
- request requirements,
- successful response,
- relevant error response,
- content type.
The API contract should be covered by automated tests.
The first slice does not require a full OpenAPI specification unless the implementation establishes one naturally.
Do not introduce API-contract tooling solely for this slice unless there is a clear project-wide benefit.
9. Testing Requirements
The vertical slice must demonstrate the project's testing strategy rather than merely contain one test.
Tests should be placed at the lowest appropriate level.
9.1 Backend unit tests
Pure backend logic that contains meaningful behavior should have unit tests where appropriate.
The trivial message retrieval itself may not require extensive unit-test coverage if there is no meaningful logic to isolate.
Do not create artificial abstractions solely to make trivial code unit-testable.
9.2 Backend integration tests
Integration testing must verify the backend's interaction with the database where appropriate.
At minimum, the project should demonstrate that backend code can retrieve persisted data using the real database infrastructure or an explicitly justified test database strategy.
9.3 API tests
The API endpoint should be tested as an HTTP-facing backend interface.
The test should verify at least:
- the endpoint exists,
- the expected HTTP status is returned,
- the response has the expected structure,
- the returned message is correct.
9.4 Frontend tests
The frontend should contain tests appropriate to the selected frontend testing strategy.
At minimum, the important behavior is:
API response
↓
frontend state
↓
message displayed
The test should verify user-visible behavior rather than implementation details whenever practical.
9.5 End-to-end test
The most important test for the vertical slice is an end-to-end test.
It must verify the complete path:
Browser
↓
React frontend
↓
HTTP API
↓
Backend
↓
Database
The E2E test should verify that the browser ultimately displays the message stored in the database.
A test that mocks the backend response does not prove the complete vertical slice.
A test that mocks the database does not prove the complete vertical slice.
Mocks may still be appropriate for lower-level tests, but at least one test must exercise the real integrated path.
10. Test Data
The vertical slice should use deterministic test data.
The expected message should be known and reproducible.
For example:
Hello from the database!
The E2E environment must initialize its own known database state.
Tests must not depend on whatever data happens to exist in a developer's local database.
Tests should be isolated from unrelated local state.
11. Docker Requirements
Docker must provide a reproducible local PostgreSQL environment.
The first slice should support a workflow conceptually equivalent to:
Start Docker services
↓
PostgreSQL starts
↓
Database is initialized
↓
Backend starts
↓
Frontend starts
↓
Application is available
Docker should be used to reduce differences between developer environments and CI.
The exact Docker architecture and commands are defined by the project's development and Docker documentation.
Do not introduce unnecessary containers.
For the first slice, PostgreSQL is the primary infrastructure requirement.
Redis is not required.
12. CI Requirements
The first vertical slice is not complete until it can be validated by CI.
CI must be able to perform the relevant automated checks from a clean checkout.
At minimum, CI should eventually verify:
- dependency installation,
- formatting,
- linting,
- type checking,
- unit tests,
- integration/API tests,
- frontend tests,
- build,
- E2E tests where the CI environment supports them.
The exact CI workflow should be defined in .github/workflows/ and documented in the appropriate
project documentation.
CI must not depend on:
- a developer's local database,
- local environment variables that are not documented,
- manually created database state,
- globally installed tools,
- undocumented machine-specific configuration.
13. Local Development Verification
A developer should eventually be able to verify the complete slice locally using documented commands.
The verification flow should be conceptually:
1. Install dependencies.
2. Start the required infrastructure.
3. Initialize the database.
4. Start the backend.
5. Start the frontend.
6. Open the application.
7. Observe the database-backed message.
8. Run automated tests.
9. Run static checks.
10. Run the production build.
11. Run the E2E test.
The exact commands belong in docs/development.md and should be updated as the repository tooling
is implemented.
14. Acceptance Criteria
The vertical slice is complete only when all of the following are true and the project Definition of Done is satisfied. Early allowances in this specification for deferred CI/E2E or optional API tooling do not waive the currently implemented CI, Playwright, and OpenAPI requirements.
Repository
- The repository contains the expected frontend, backend, documentation, test, Docker, and CI structure required by the implementation.
- The project uses the documented technology stack.
- Dependencies are reproducibly installed.
- No undocumented global dependency is required.
Database
- PostgreSQL starts successfully.
- Database configuration is externalized.
- The schema can be created reproducibly.
- The required message data can be initialized reproducibly.
- A fresh database can be used without manual table creation.
Backend
- The backend starts successfully.
- The backend connects to PostgreSQL.
- The backend retrieves the message from PostgreSQL.
-
GET /api/messageworks. - The API response follows the documented contract.
- Basic database/API failure behavior is handled appropriately.
Frontend
- The frontend starts successfully.
- The frontend communicates with the backend.
- The frontend displays the value returned by the backend.
- The message is not hard-coded as the source of displayed data.
- Basic loading/error behavior is implemented where appropriate.
Testing
- Appropriate backend unit tests exist.
- Backend/database integration behavior is tested.
- The API contract is tested.
- Appropriate frontend behavior is tested.
- An E2E test verifies the complete database-to-browser path.
- Tests are deterministic and reproducible.
Docker
- Required infrastructure can be started through Docker.
- PostgreSQL configuration is reproducible.
- The application does not depend on manually configured local infrastructure.
CI
- CI installs dependencies successfully.
- CI runs static checks.
- CI runs automated tests.
- CI can build the application.
- CI can execute the E2E test or the E2E environment is explicitly documented if temporarily deferred.
Documentation
-
AGENTS.mddescribes the project rules. -
docs/architecture.mddescribes the architecture. -
docs/development.mddescribes development and verification. - This document describes the vertical slice.
- The actual commands and repository structure are documented once they exist.
- Any temporary limitation is explicitly documented.
15. Definition of Success
The strongest demonstration of success is:
- Start from a clean checkout.
- Start the documented infrastructure.
- Initialize a fresh PostgreSQL database.
- Start the application.
- Open the frontend in a browser.
- The browser displays:
Hello from the database!
- Change the value in the database through the project's reproducible initialization/test mechanism.
- Restart or reload the application as appropriate.
- The browser displays the new database value.
- Automated tests verify the same path.
- CI reproduces the relevant verification successfully.
This demonstrates that the displayed value is genuinely flowing through:
PostgreSQL
→ backend data access
→ backend application/API
→ HTTP
→ React
→ browser
That is the core technical proof of the first vertical slice.
16. Implementation Principles
The implementation should follow these principles.
Keep the feature intentionally trivial
The message is a technical proving ground.
Do not turn it into a user-management system, content-management system, or generalized CRUD framework.
Prefer real integration over artificial abstraction
The goal is to prove that the actual technologies work together.
Do not replace PostgreSQL with an in-memory repository merely to simplify tests.
Do not mock the entire backend in the E2E test.
Do not introduce abstractions whose only purpose is to make this trivial feature look architecturally sophisticated.
Introduce infrastructure only when justified
Every dependency and infrastructure component should have a concrete purpose.
The first slice does not need:
- Redis,
- WebSockets,
- message brokers,
- authentication providers,
- payment providers,
- external APIs,
- production deployment infrastructure.
Keep boundaries clear
Even though the feature is tiny, it should establish the project's intended boundaries.
The implementation should make it possible to add real functionality later without immediately restructuring the application.
Make failures visible
A passing test suite must represent real verification.
Do not:
- skip failing tests,
- weaken assertions merely to make tests pass,
- mock away the behavior being tested,
- report checks as successful when they were not run.
If something cannot yet be verified, document the limitation explicitly.
17. Expected Project Evolution
The first vertical slice establishes the foundation for later slices.
Future features should preferably extend the existing path rather than create unrelated parallel architectures.
For example, a future order-related slice may eventually follow:
PostgreSQL
↓
Order persistence
↓
Order application logic
↓
Order API
↓
React order UI
↓
Browser
A later kitchen-display slice may extend this with real-time communication:
Order state
↓
Backend
↓
Real-time mechanism
↓
Kitchen display
A payment slice may introduce:
Application
↓
Payment capability
↓
Payment provider adapter
↓
External payment service
Those capabilities are deliberately outside the first slice.
The architecture should therefore be designed to evolve toward them without requiring them prematurely.
18. Relationship to Other Documentation
This document defines what the first technical milestone must prove.
Other documents define different aspects of the project:
| Document | Responsibility |
|---|---|
AGENTS.md |
Rules and instructions for humans and AI agents |
docs/techstack.md |
Technology choices |
docs/architecture.md |
Architectural structure and boundaries |
docs/development.md |
How to develop and verify the application |
docs/test-strategy.md |
Overall testing strategy |
docs/specs/001-vertical-slice/vertical-slice.md |
Exact requirements for the first vertical slice |
docs/current-state.md |
Current implementation state and next step |
If these documents appear to conflict, resolve the conflict explicitly rather than silently choosing one.
Implementation-specific details should not be duplicated unnecessarily across documents.
19. AI Agent Guidance
An AI coding agent implementing this slice should work incrementally.
Before making changes:
- Read
AGENTS.md. - Read
docs/architecture.md. - Read
docs/development.md. - Read
docs/test-strategy.md. - Read this document.
- Inspect the current repository state.
- Check
git status. - Read
docs/current-state.mdif it exists.
Then implement the smallest coherent next step.
After each meaningful change:
- Run the relevant tests.
- Run formatting/lint/type checks as applicable.
- Verify the implementation against this specification.
- Update documentation when the actual repository behavior becomes known.
- Update
docs/current-state.md. - Leave the repository in a usable state.
Do not assume that conversation history is the project's only source of progress.
The repository itself must contain enough information for another AI agent or developer to continue the work.
20. Completion Report
When the vertical slice is considered complete, the implementation should be accompanied by a concise verification report containing:
- what was implemented,
- files/components added or changed,
- commands executed,
- tests executed,
- test results,
- static checks executed,
- build result,
- E2E result,
- Docker verification,
- CI verification,
- known limitations,
- recommended next step.
An AI agent must distinguish between:
Verified
and:
Not verified
It must not claim successful execution of commands or tests that it did not actually run.
21. Next Step After Completion
Once this vertical slice satisfies the Definition of Done, the project should not immediately expand into a large feature set.
The next step should be selected as the smallest useful vertical slice that adds genuine application functionality while reusing the proven technical foundation.
The project should continue to grow through small, independently verifiable vertical slices rather than completing entire technical layers in isolation.