TypeSmart is a full-stack, real-time intelligent suggestion editor inspired by Smart Compose. It offers word suggestions on the fly as the user types into a rich text editor. This project demonstrates a complete system including a frontend React editor, Spring Boot microservices, Eureka service discovery, and a Levenshtein-based suggestion engine.
- โ Smart floating suggestion panel
- โ Real-time suggestions as you type
- โ Custom Levenshtein distance algorithm
- โ Microservices architecture with Spring Boot
- โ Eureka Discovery + Spring Cloud Gateway
- โ Modern React UI with TailwindCSS
| Layer | Technology |
|---|---|
| Frontend | React, TipTap Editor, TailwindCSS |
| Backend | Spring Boot (Java 17+) |
| Discovery | Eureka Discovery Server |
| Gateway | Spring Cloud Gateway |
| Editor Logic | Levenshtein Distance (Custom Java) |
typesmart/
โโโ frontend/
โ โโโ src/
โ โ โโโ App.js
โ โ โโโ components/Editor.js
โ โโโ tailwind.css
โ
โโโ api-gateway/
โ โโโ ApiGatewayApplication.java
โ โโโ application.properties
โ
โโโ discovery-service/
โ โโโ DiscoveryServerApplication.java
โ โโโ application.properties
โ
โโโ suggestion-service/
โ โโโ config/
โ โโโ controller/
โ โโโ service/
โ โโโ model/
โ โโโ util/
โ โโโ application.properties
โ
โโโ README.md
- Uses
@tiptap/reactandStarterKitto build a rich text editor. - Detects the current word while typing and makes debounced API calls for suggestions.
- Suggestion panel appears just below the current cursor with matching suggestions.
useEffect(() => {
const text = editor.getText();
const words = text.split(/\s+/);
const lastWord = words[words.length - 1] || '';
...
fetchSuggestions(lastWord);
}, []);@import "tailwindcss";
.ProseMirror {
min-height: 200px;
outline: none;
}ApiGatewayApplication.java
@SpringBootApplication
@EnableDiscoveryClient
public class ApiGatewayApplication {
public static void main(String[] args) {
SpringApplication.run(ApiGatewayApplication.class, args);
}
}application.properties
spring.application.name=api-gateway
server.port=8080
spring.cloud.gateway.discovery.locator.enabled=true
spring.cloud.gateway.discovery.locator.lower-case-service-id=true
eureka.client.service-url.defaultZone=http://localhost:8761/eurekaDiscoveryServerApplication.java
@SpringBootApplication
@EnableEurekaServer
public class DiscoveryServerApplication {
public static void main(String[] args) {
SpringApplication.run(DiscoveryServerApplication.class, args);
}
}application.properties
spring.application.name=discovery-service
server.port=8761
eureka.client.register-with-eureka=false
eureka.client.fetch-registry=false
eureka.server.wait-time-in-ms-when-sync-empty=0-
Provides real-time suggestions based on Levenshtein similarity.
-
SuggestionService.java
@PostConstruct
public void init() throws IOException {
dictionary = new HashSet<>();
ClassPathResource resource = new ClassPathResource("dictionary.txt");
try (BufferedReader reader = new BufferedReader(new InputStreamReader(resource.getInputStream()))) {
String word;
while ((word = reader.readLine()) != null) {
dictionary.add(word.trim().toLowerCase());
}
}
}SuggestionController.java
@GetMapping
public ResponseEntity<SuggestionResponse> getSuggestions(@RequestParam String word) {
List<String> suggestions = suggestionService.suggest(word);
return ResponseEntity.ok(new SuggestionResponse(word, suggestions));
}LevenshteinUtil.java
public static int calculate(String a, String b) {
int[][] dp = new int[a.length() + 1][b.length() + 1];
// ...
return dp[a.length()][b.length()];
}application.properties
spring.application.name=suggestion-service
server.port=8081
eureka.client.service-url.defaultZone=http://localhost:8761/eureka/The Levenshtein algorithm calculates the minimum number of single-character edits required to change one word into another. It uses dynamic programming with a 2D matrix.
Let:
m= length of input word (typed by user)n= length of dictionary wordD= total number of words in the dictionary
| Metric | Complexity |
|---|---|
| Single comparison | O(m ร n) |
| Suggestion lookup | O(D ร m ร n) |
| Space per comparison | O(m ร n) |
The current implementation sorts all dictionary words by their Levenshtein distance and selects the top 5.
Optimization: To improve performance for large dictionaries, I am planning to add a Trie or use BK-Trees for approximate matching in
O(log D)time.
- Place dictionary.txt in src/main/resources/ of the Suggestion Service.
hello
world
spring
boot
editor
text
input
react
...- Ensure below ports are available
- 3000 (frontend)
- 8080 (gateway)
- 8081 (suggestion)
- 8761 (eureka)
- Start Eureka
cd discovery-service
mvn spring-boot:run- Start Gateway
cd api-gateway
mvn spring-boot:run- Start Suggestion Service
cd suggestion-service
mvn spring-boot:run- Start React Frontend
cd frontend
npm install
npm startGET - /api/suggestions?word=helo
{
"word": "helo",
"suggestions": ["halo", "held", "hele", "hell", "helm"]
}- Keyboard navigation (โ โ Enter)
- Add Docker support
- Deploy on Render/Netlify + Fly.io
- ML-powered suggestions
Konark Lohat
Full Stack Developer | React + Spring Boot | Deloitte โ Product Companies
This project is open source and available under the MIT License.
