design – Building a Microservices App — Can you give feedback on architecture?

I did some googling, and I was directed to Software Engineering to ask architecture questions. If you know of a different forum that could help me, please direct me to it

I recently started learning about microservices, and would like to build an experimental app (the backend) just for practice. I’ll explain the app requirements, and after that outline my microservices-based solutions (and some doubts/questions I have). I’d love to get your feedback, or your approach to building this app using microservices.

Please note: I am a beginner when it comes to microservices, and still learning. My solution might not be good, so I’d like to learn from you.

The App (Silly App):

The purpose of this app is to make sure users eat carrots four times a week. App admins create a carrot eating competition that starts on day x and ends 8 weeks after day x. Users can choose whether or not to participate in the competition. When a user joins the competition, they need to post a picture of themselves eating a carrot. The admin approves/rejects the picture. If approved, the carrot eating session counts towards the weekly goal, otherwise it does not. At the end of each week, participating users are billed $10 for each carrot eating session they missed (for example, if they only eat carrots two times that week, they’re billed $20). That $20 goes into a “money bucket”. At the end of two months, users who successfully ate carrots four times a week every single week divide the money in the bucket among themselves. For example, assume we have users A, B, C. User A missed all carrot eating sessions for two months (puts $40 a week in the money bucket, so $320 by the end of two months). Users B and C eat their carrots four times a week consistently for two months. So users B and C take home $320/2 = $160.

Simplification:
I wanted to start simple. Forget about money. Forget about admin approval. We can add that later. For now, let’s focus on a very simplified version of the app.

  • User can signup/login/logout to app
  • When a user signs up, they are automatically enrolled into the next carrot eating competition
  • Users can post an image of him/herself eating a carrot
  • Users can see a feed of other users images (similar to instagram, except all pics are of people eating carrots)
  • Users can access their profile – a page that displays how they’re doing in the competition: I.e,for each week, how many carrots they ate. And which weeks they failed at.
  • At any point in time, users can access a page that shows who the current winners are (i.e, users who did not miss a carrot eating session yet).

Is this an appropriate simplification to start with?

Thinking Microservices – Asynchronous Approach:

Auth Service: Responsible for Authenticating User

Database:

  • User Table: id, username, email, password

Routes:

  • POST /users/new : signup
  • POST /users/login: login
  • POST /users/signout: signout

Events:

Image Service: Responsible for Saving Images (upload to Amazon S3)

Database:

  • User Table: userId, username
  • Image Table: imageId, userId, dateUploaded, imageUrl

Routes:

  • POST /users/:userId/images: Post new image
  • GET /users/:userId/image/:imageId: Return a specific image
  • GET /images: Return all images (Feed)

Events:

  • Publishes:
    • Image:created (userId, imageId, imageUrl, dateUploaded)

Competition Service: Responsible for managing competition

Database:

  • Competition table: id, startDate, duration
  • User table: id, username, competitionId, results (see below)

Routes:

  • POST /competition: create a competition
  • GET /competition/:competitionId/users/:userId: get results for a specific user
  • GET /competition/:competitionId/users: get a list of users participating in competition (see below)
  • GET /competition/:competitionId: get a list of winners, and for each looser how many workouts they missed

Events:

  • Listens:
    • User:created
    • Image:created

In the database, user table, Results is the JSON equivalent of

results = {
   week1: {
       date: 'oct 20 2020 - oct 27 2020',
       results: ('mon oct 20 2020', 'tue oct 21 2020', 'thur oct 23 2020'),
   },
   week2: {
       date: 'oct 28 2020 - nov4 2020',
       results: ('somedate', 'somedate', 'somedate', 'somedate'),
   },
   week3: {
       date: 'nov 5 2020 - nov 12 2020',
       results: (),
   },
   ...
}

Better ideas on how to store this data appreciated

GET /competition/:competitionId returns

const results: {
 winners: ({ userId: 'jkjl'; username: 'jkljkl' }, { userId: 'jkjl'; username: 'jkljkl' });
 loosers: (
   { userId: 'kffjl'; username: 'klj'; carrotDaysMissed: 3 },
   { userId: 'kl'; username: 'kdddfj'; carrotDaysMissed: 2 }
 );
};

What do you think of this? How would you improve it? Or would you approach this from an entirely different way?

web development – what is the next step after learning and building forms and databases

I am trying to shift my career into software. I have been doing self education mostly using YouTube videos. I have understood how form submission works and how a server accepts the data from form submission and saves it in a database. i taught myself crud operations and creating a rest API server that writes and reads to/from a database. what would be beneficial to my learning next ? what should i focus my efforts on ?

❓ASK – Building up your audience on YouTube | Proxies-free

You have to think of unique videos that can make your viewers subscribe to you channel. Some beginner are making stories, so their subscribers will keep watching their vids and share it on social media sites. Some do make films, tutorials, popular game techniques demos, music cover, anything that is on trend that will atrract the viewers might work.

 

I will provide 100 SEO backlinks white hat manual link building service for google top ranking for $70

I will provide 100 SEO backlinks white hat manual link building service for google top ranking



** Over 4 Years of Experience Providing Dofollow SEO Backlinks **

If you want to see mypreviouse seo service sample ,i will send you.

Making Dofollow Backlinks From High Domains (DR 80 TO 60) is Very Important in GOOGLE SEO and Ranking

For This Purpose I am Here to Provide such a unique High Quality Domains For white Hat Dofollow SEO Backlinks

I ensure of you that your website 100% guaranteed will be 1ST page ranking on google

If you are looking to Guaranteed your Google Rankings to First Page with a White Hat Off Page SEO Service then you are at the right gig.

Off Page Search Engine Optimization Strategy.

I do competitor Analysis first, and I have my strategies to build backlinks for a top Ranking in Google with White Hat Links.

Some Notable Mentions:

All our High Quality SEO Backlinks are Created Manually and assure a solid link building campaign.

1 High Metric Backlink = 10 low metric Backlinks.

High Quality Manual Link Building is hard to find.

All our backlinks are Dofollow.

What Will You Get?

1,Social bookmarking

2,forum posting

3,answers posting

4,Directory submission

5,Article submission

6,web 2.0

7,Doc Share

8,Guest Post

9,Video submission

10,slide share

The Value You Will Get

– Improved Rankings

– Permanent Links

– Enhanced Domain Authority

– Sustained Website Growth
If you anyQuestion , please contact me without hesitation

.(tagsToTranslate)seo(t)dofollow(t)backlin(t)website(t)ranking(t)backlinks(t)backlink(t)seo

unit testing – Building a GTD Productivity App Designed through Test Driven Development (TDD)

First, thanks so much for looking at my code. Over the past decade, I have tried every task management apps imaginable. I finally realized that the only way I would ever find my perfect productivity system is if I build it myself.

To this end, I am creating ClearHeadTodo, a productivity app that seeks to bring the GTD model of productivity using entirely rust if possible.

While for now i’m only focused on the Command Line Interface (CLI) my ultimate goal is to make this a modular piece of software where the core productivity system works no matter what medium you are utilizing (GUI or CLI)

The Question: Control Flow Best-Practices for Testing and Scalability

The Code: 2 Main Files
For now, most of this work is broken into two files (lib.rs and main.rs respectively)

  • lib.rs contains the main logic for the Task List
  • While main.rs contains the CLI struct which the user actually interacts with to alter the task objects.

Current Code Status
For right now, users can only create tasks. Tasks have a name, priority, and completion status.

  • This is all loaded to and from a vector using a .csv to reduce database complexity

I’m very proud to say that everything works from all my testing, however, now that the code is all together, it feels… difficult to scale the code base since the main command loop is basically just a huge match statement.

I want to use best-practices like the result data type, but i am having trouble formatting the code in such a way that would propagate the result of each function properly to the end of the main command line.

Specifically, whenever i try using the ?, it throws an error saying that i’m not using the proper type (even though you can see there are several results in this code)

Operation all work is done through just running the main rust build with any arguments,
so cargo run create_task will create a new task which can be shown with `cargo run list_task
Main.rs

use std::io::{self, Write};
use std::io::stdout;
use clear_head_todo::TaskList;
use clear_head_todo::PriEnum;
use std::path::Path;

pub struct CLI{
    pub pattern: Option<String>,
    pub index: Option<String>,
    pub input: Option<String>,
    pub task_vec: TaskList
}

impl CLI {
        pub fn parse_arguments(&mut self) {
            match self.pattern.as_ref().unwrap_or(
                &"no command given".to_string()) as &str{
            "create_task" | "create" | "ct" | "new_task" | "new" =>
                self.task_vec
                .create_task(),
            "list_tasks" | "lt" | "list" | "list_all" =>
                self.task_vec.print_task_list(std::io::stdout()).unwrap_or(()),
            "remove_task" | "remove" | "rt" | "delete_task" | "delete" =>
                self.task_vec
                .remove_task(
                    self.index.as_ref()
                    .unwrap()
                    .to_string()
                    .parse::<usize>()
                    .unwrap(), 
                    io::stdout())
                    .expect("invalid index"),
            "complete_task" | "complete" | "mark_complete" =>
                self.task_vec.tasks(
                self.index.as_ref()
                .unwrap()
                .parse::<usize>()
                .unwrap())
                .mark_complete(),
            "change_priority" | "cp" | "new_priority" | "np" =>
                self.task_vec.tasks(
                self.index.as_ref()
                .unwrap()
                .parse::<usize>()
                .unwrap())
                .change_priority(
                        &self.input.as_ref().unwrap()(..)),
            "rename_task" | "rename" | "name" | "r" =>
                self.task_vec.tasks(
                self.index.as_ref()
               .unwrap()
               .parse::<usize>()
               .unwrap())
               .rename_task(
                    self.input.as_ref()
                   .unwrap()),
            _ => return
            };
    }
    pub fn cli_list_tasks(&self, mut writer: impl std::io::Write){
        self.task_vec.print_task_list(writer).unwrap_or(());
    }
}
fn main() {

    println!("starting program");
    
    let mut main_cli: CLI = CLI{
        pattern : std::env::args().nth(1),
        index: std::env::args().nth(2),
        input: std::env::args().nth(3),
        task_vec: TaskList{
            tasks: vec!()
        }
    };

    main_cli.task_vec.load_tasks("tasks.csv").unwrap();
    
    main_cli.parse_arguments();

    main_cli.task_vec.load_csv("tasks.csv").unwrap();
    
}

#(cfg(test))
mod tests {
    use super::*;

    #(test)
    fn cli_creation_test () {
        let mut test_cli = CLI {
            pattern: None, 
            index: None,
            input: None,
            task_vec: TaskList{tasks: vec!()}, 

        };
        assert!(test_cli.pattern == None);
        assert!(test_cli.index == None);
        assert!(test_cli.input == None);
        assert!(test_cli.task_vec.tasks.len() == 0);
        test_cli.parse_arguments();
    }

    #(test)
    fn cli_task_creation_test () {
        let mut test_cli = CLI {
            pattern: Some("create_task".to_string()), 
            index: None,
            input: None,
            task_vec: TaskList{tasks: vec!()}, 

        };
        test_cli.parse_arguments();
        assert!(test_cli.task_vec.tasks.len() == 1);
        assert!(test_cli.task_vec.tasks(0).name == "Test Task");
        assert!(test_cli.task_vec.tasks(0).completed == false);
        assert!(test_cli.task_vec.tasks(0).priority == PriEnum::Optional);
    }

    #(test)
    fn cli_task_list_test () {
        //let mut good_result = Vec::new();
        let mut test_cli = CLI {
            pattern: Some("list_tasks".to_string()), 
            index: None,
            input: None,
            task_vec: TaskList{tasks: vec!()}, 

        };

        test_cli.parse_arguments();
    }
}


Lib.rs (logical center of the app)

use std::error::Error;
use std::io::{Error as OtherError, ErrorKind};
use std::fmt;
use csv::Reader;
use csv::Writer;
use std::path::{Path, PathBuf};
use std::env;
use std::str::FromStr;
use serde::ser::{Serialize, SerializeStruct, Serializer};
use serde::Serialize as AltSerialize;

pub struct TaskList {
    pub tasks: Vec<Task>
}

#(derive(PartialEq))
#(derive(Debug))
#(repr(u8))
#(derive(AltSerialize))
pub enum PriEnum {
    Critical = 1,
    High = 2,
    Medium = 3,
    Low = 4,
    Optional = 5,
}

impl fmt::Display for PriEnum {
    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
        let printable: &str = match *self {
            PriEnum::Critical => "Critical",
            PriEnum::High => "High",
            PriEnum::Medium => "Medium",
            PriEnum::Low => "Low",
            PriEnum::Optional => "Optional"
        };
        write!(f, "{}", printable)
    }
}

impl Serialize for Task {
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error> 
    where
            S: Serializer, 
        {
            let mut s = serializer.serialize_struct("Task", 3)?;
            s.serialize_field("name", &self.name)?;
            s.serialize_field("priority", &self.priority)?;
            s.serialize_field("completed", &self.completed)?;
            s.end()
        }
}
 
pub fn parse_priority(expr: &str) -> Result<PriEnum, String> {
    match expr.to_ascii_lowercase().trim() {
        "1" | "critical" | "crit" | "c" => Ok(PriEnum::Critical),
        "2" | "high" | "hi" | "h" => Ok(PriEnum::High),
        "3" | "medium" | "med" | "m" => Ok(PriEnum::Medium),
        "4" | "low" | "lo" | "l" => Ok(PriEnum::Low),
        "5" | "optional" | "opt" | "o" => Ok(PriEnum::Optional),
        "" => Ok(PriEnum::Optional), //defaults to this
        _ => Err(format!("Invalid priority value")),
    }
}

#(derive(PartialEq, Debug))
pub struct Task {
    pub name: String,
    pub completed: bool,
    pub priority: PriEnum, 
}

impl TaskList {
    //load tasks from either tasks.csv or testTasks.csv using the file_name
    pub fn load_tasks(&mut self, file_name: &str) -> Result<(), Box<dyn Error>> {
        let pathbuf = env::current_dir().unwrap().join("data").join(file_name);
        let mut rdr: Reader<std::fs::File> = Reader::from_path(pathbuf)?;
        for result in rdr.records() { 
            let record = result?;
            let new_task = Task {
                name: record(0).to_string(),
                completed: FromStr::from_str(&record(2))?,
                priority : parse_priority(&record(1))?,
            };
            self.tasks.push(new_task);
        }
        Ok(())
    }

    pub fn load_csv(&mut self, file_name: &str) -> Result<(), Box<dyn Error>> {
        let pathbuf = env::current_dir().unwrap().join("data").join(file_name);
        let mut wtr: Writer<std::fs::File> = Writer::from_path(pathbuf)?;
        for index in 0..=self.tasks.len()-1{
            wtr.serialize::<_>(&self.tasks(index)).unwrap();
        }
        Ok(())
    }

    pub fn create_task(&mut self) {
        let new_task: Task = Task {
            name: String::from("Test Task"),
            completed: false,
            priority: PriEnum::Optional,
        };
        self.tasks.push(new_task);
    }
    
    pub fn print_task_list(&self, mut writer: impl std::io::Write)->
    Result<(), std::io::Error> {
        if self.tasks.is_empty()==true{
            return Err(OtherError::new(ErrorKind::Other, "list is empty"));
        } else{
            for index in 0..=self.tasks.len()-1 {
                writeln!(writer, "{index},{name},{priority},{completed}",
                        index = index,
                        name = self.tasks(index).name,
                        priority = self.tasks(index).priority,
                        completed = self.tasks(index).completed)?;
            }
        }
        Ok(())
    }
    
    pub fn remove_task(&mut self, index: usize, mut writer: impl std::io::Write) -> 
    Result<(), std::io::Error>  {
        if index < self.tasks.len() {
            writeln!(writer, "Deleted {name} Task", 
                     name = self.tasks(index).name)?; 
            self.tasks.remove(index);
            return Ok(());
        }
        else {
            return Err(OtherError::new(ErrorKind::Other, "Invalid Index for Deletion"));
        }
    }

} //end 'impl TaskList'
 

impl Task {
    pub fn rename_task(&mut self, new_task_name: &String) {
        self.name = new_task_name.to_owned();
    }
    
    pub fn mark_complete(&mut self) {
        self.completed = true;
    }
    
    pub fn change_priority(&mut self, new_priority: &str) {
        let new_pri = parse_priority(new_priority);
        match new_pri {
            Ok(i) => self.priority = i,
            Err(err) => println!("{}", err),
        };
        
    }
   
} //end 'impl Task'

#(cfg(test))
mod tests {
    use super::*;
    
    #(test)
    fn task_creation_test() {
        let mut test_task_list = TaskList{tasks: vec!()}; 
        test_task_list.create_task();
        let test_task = &test_task_list.tasks(0);
        assert!(test_task.name == "Test Task");
        assert!(test_task.completed == false);
        assert!(test_task.priority == PriEnum::Optional);
        assert!(&test_task_list.tasks(0) == test_task);
    }
    
    #(test)
    fn task_rename_test() {
        let mut test_task_list = TaskList{tasks: vec!()}; 
        test_task_list.create_task();         
        let test_task = &mut test_task_list.tasks(0);
        test_task.rename_task(&"Changed Name".to_string());
        assert!(test_task.name == "Changed Name");
    }
    
    #(test)
    fn task_completion_test() {
        let mut test_task_list = TaskList{tasks: vec!()}; 
        test_task_list.create_task();
        let test_task = &mut test_task_list.tasks(0);
        test_task.mark_complete();
        assert!(test_task.completed == true);
    }
    
    #(test)
    fn task_successful_removal_test() {
        let mut test_task_list = TaskList{tasks: vec!()};
        let mut good_result = Vec::new();
        test_task_list.create_task();
        test_task_list.remove_task(0, &mut good_result).unwrap();
        assert!(test_task_list.tasks.is_empty());
        assert_eq!(&good_result(..), "Deleted Test Task Taskn".as_bytes());
    }
    
    #(test)
    fn task_removal_fail_test(){
        let mut test_task_list = TaskList{tasks: vec!()};
        let mut bad_result = Vec::new();
        let error = test_task_list.remove_task(0, &mut bad_result).unwrap_err();
        assert_eq!(error.to_string(), "Invalid Index for Deletion");
    }

    #(test)
    fn task_reprioritize_test() {
        let mut test_task_list = TaskList{tasks: vec!()}; 
        test_task_list.create_task();
        let test_task = &mut test_task_list.tasks(0);
        println!("{}", test_task.name);
        test_task.change_priority("4");
        assert!(test_task.priority == PriEnum::Low);
        test_task.change_priority("3");
        assert!(test_task.priority == PriEnum::Medium);
        test_task.change_priority("2");
        assert!(test_task.priority == PriEnum::High);
        test_task.change_priority("1");
        assert!(test_task.priority == PriEnum::Critical);
        test_task.change_priority("6");
        assert!(test_task.priority == PriEnum::Critical); //should NOT change on bad input
    }
    
    #(test)
    fn task_print_fail_test(){
        let test_task_list = TaskList{tasks: vec!()};
        let mut bad_result = Vec::new();
        let error = test_task_list.print_task_list(&mut bad_result).unwrap_err();
        assert_eq!(error.to_string(), "list is empty");
    }
    #(test)
    fn task_print_full_test(){
        let mut test_task_list = TaskList{tasks: vec!()};
        let mut good_result = Vec::new();
        test_task_list.create_task();
        test_task_list.print_task_list(&mut good_result).unwrap();
        assert_eq!(&good_result(..), "0,Test Task,Optional,falsen".as_bytes());
    }
    
    #(test)
    fn load_from_csv_sucessful_test(){
        let mut test_task_list = TaskList{tasks: vec!()};
        test_task_list.load_tasks("testTasks.csv").unwrap();
        let test_task = &test_task_list.tasks(0);
        assert!(test_task.name == "test csv task");
        assert!(test_task.completed == false);
        assert!(test_task.priority == PriEnum::Optional);
    }

    #(test)
    fn load_from_csv_fail_test(){
        let mut test_task_list = TaskList{tasks: vec!()};
        let error = test_task_list.load_tasks("bad_file").unwrap_err();
        assert!(error.to_string().contains("(os error 2)"));
    }
    
    #(test)
    fn load_to_csv_successful_test(){
        let mut test_task_list = TaskList{tasks: vec!()};
        test_task_list.create_task();
        test_task_list.tasks(0).rename_task(&"test csv task".to_string());
        test_task_list.load_csv("testTask.csv").unwrap();
        let rdr = Reader::from_path(
            env::current_dir().unwrap().join("data").join("testTasks.csv").as_path())
            .unwrap();
        let mut iter = rdr.into_records();
        if let Some(result) = iter.next() {
            let record = result.unwrap();
            assert_eq!(record, vec!("test csv task", "Optional", "false"));
        }
    }

}

Again, Thank you for taking the time to look at this, everything should run if you put these in a cargo project, if even cargo test fails, please send me the error code

200+ Manual Dofollow Backlinks Web2, PBN, Profile, Wiki, Bookmark & Link Building Service for $20

200+ Manual Dofollow Backlinks Web2, PBN, Profile, Wiki, Bookmark & Link Building Service

If you need the Highest Quality & Most Effective Dofollow Backlinks then you are just at the right place.

Looking for Diversified backlinks to boost your website’s ranking?

Just got way better after the Latest Google Update

Do you need SEO services? Now you are in right place! 100% Organic & White hat Services! Trust SEO BD Provide Worldwide SEO services for small and big business. We ensure you can generate organic traffic and

sales within a short time. This package is a sample that what we work. Basically, We are not waiting for this packages but We use all SEO technique to rank higher.

We provide white hat SEO service that is long-lasting and Google also loves white hat SEO. In the world have a lot of SEO packages and service, some package gives very cheap prices for growing your business but you are waiting for Google penalty. Choose the white hat SEO! Our Some clients already penalty from some service provider. So don’t avoid it! If you like our Services so don’t be late contact us!!

Using my tried and tested strategy I can provide you with the following:

– Increased website authority

– Top-ranked website based on keywords

– Manually built backlinks with only high PR site, using unique content

– Google Penguin 3.0 and Panda 4.1 safe work

– 100% White Hat, manual work only

– Totally Unique articles

– Flawless Approval rate

– Do-follow backlinks

– Only a Natural mix of anchored and non-anchored high PR backlinks

– Full reports and Logins

100 Dofollow Quality Manual Backlinks From Different Platforms


Backlinks you will get from these platforms:

  • Article Posting Sites
  • Press Release Distribution Sites
  • PDF/Doc Sharing Sites
  • Web 2.0 Blog Posting Sites
  • Top Social bookmarking Sites
  • Top Video Sharing Sites
  • Classified Ad Posting Sites
  • High Quality Blog Site
  • Social Sharing Sites

Using my tried and tested strategy I can provide you with the following:

★ Increased website authority

★ Top-ranked website based on keywords

★ Manually built backlinks with only high PR site, using unique content

★ Google Penguin 3.0 and Panda 4.1 safe work

★ 100% White Hat, manual work only

★ Totally Unique articles

★ Relevant Article

★ Friendly Customer Service

★ Do-follow backlinks

★ Only a Natural mix of anchored and non-anchored high PR backlinks

★ Finally, I Will Provide Complete report delivery.

★ On Time Delivery.

★ 100% Maney back grantee.

★ Fastest Ranking Improvement

★ 100% Google Index

★ Permanent Роst

★ Get More Traffic

★ 100 % Highly Еffесtіvе

★ Boost Уоur Wеbsіtеs Ranking

What We Need From You:

Your Website Link, targeted keywords & urls.

FAQ:


Will I get ranking in Search Engine?

Nope. Ranking matters lots of things & it’s just a $5 job. Our Service will give just a boost in your website’s ranking.

Will all backlinks index in Search Engine?

Nope. All 100 backlinks will not index in SE. We don’t grantee how many will get index.

Do you create only dofollow links?

Most of the links will be dofollow and few will be nofollow links, are always good for your link profile.

Will you write a fresh content?

No, we don’t write fresh content. We search content related to your topic & spin it in every posting.

★★★Grab the Service Now to Boost Up you Ranking In search Engines ★★★

.

50+ Manual Dofollow Backlinks Web2, PBN, Profile, Wiki, Bookmark & Link Building Service for $5

50+ Manual Dofollow Backlinks Web2, PBN, Profile, Wiki, Bookmark & Link Building Service

If you need the Highest Quality & Most Effective Dofollow Backlinks then you are just at the right place.

Looking for Diversified backlinks to boost your website’s ranking?

Just got way better after the Latest Google Update

Do you need SEO services? Now you are in right place! 100% Organic & White hat Services! Trust SEO BD Provide Worldwide SEO services for small and big business. We ensure you can generate organic traffic and

sales within a short time. This package is a sample that what we work. Basically, We are not waiting for this packages but We use all SEO technique to rank higher.

We provide white hat SEO service that is long-lasting and Google also loves white hat SEO. In the world have a lot of SEO packages and service, some package gives very cheap prices for growing your business but you are waiting for Google penalty. Choose the white hat SEO! Our Some clients already penalty from some service provider. So don’t avoid it! If you like our Services so don’t be late contact us!!

Using my tried and tested strategy I can provide you with the following:

– Increased website authority

– Top-ranked website based on keywords

– Manually built backlinks with only high PR site, using unique content

– Google Penguin 3.0 and Panda 4.1 safe work

– 100% White Hat, manual work only

– Totally Unique articles

– Flawless Approval rate

– Do-follow backlinks

– Only a Natural mix of anchored and non-anchored high PR backlinks

– Full reports and Logins

100 Dofollow Quality Manual Backlinks From Different Platforms

Backlinks you will get from these platforms:

  • Article Posting Sites
  • Press Release Distribution Sites
  • PDF/Doc Sharing Sites
  • Web 2.0 Blog Posting Sites
  • Top Social bookmarking Sites
  • Top Video Sharing Sites
  • Classified Ad Posting Sites
  • High Quality Blog Site
  • Social Sharing Sites

Using my tried and tested strategy I can provide you with the following:

★ Increased website authority

★ Top-ranked website based on keywords

★ Manually built backlinks with only high PR site, using unique content

★ Google Penguin 3.0 and Panda 4.1 safe work

★ 100% White Hat, manual work only

★ Totally Unique articles

★ Relevant Article

★ Friendly Customer Service

★ Do-follow backlinks

★ Only a Natural mix of anchored and non-anchored high PR backlinks

★ Finally, I Will Provide Complete report delivery.

★ On Time Delivery.

★ 100% Maney back grantee.

★ Fastest Ranking Improvement

★ 100% Google Index

★ Permanent Роst

★ Get More Traffic

★ 100 % Highly Еffесtіvе

★ Boost Уоur Wеbsіtеs Ranking

What We Need From You:

Your Website Link, targeted keywords & urls.

FAQ:


Will I get ranking in Search Engine?

Nope. Ranking matters lots of things & it’s just a $5 job. Our Service will give just a boost in your website’s ranking.

Will all backlinks index in Search Engine?

Nope. All 100 backlinks will not index in SE. We don’t grantee how many will get index.

Do you create only dofollow links?

Most of the links will be dofollow and few will be nofollow links, are always good for your link profile.

Will you write a fresh content?

No, we don’t write fresh content. We search content related to your topic & spin it in every posting.

★★★Grab the Service Now to Boost Up you Ranking In search Engines ★★★

.

Build 50 Dofollow Blog Comments Backlinks High DA Website Ranking & Link Building Service for $3

Build 50 Dofollow Blog Comments Backlinks High DA Website Ranking & Link Building Service

Here is our Best SEO Service

Manual Dofollow Blog Commenting backlinks is most reliable and powerful link building method in SEO marketing. Are you looking for High Authority, Trust Flow, Citation Flow , Dofollow Blog Comments? So, we heartily welcome you to our Blog Comments service. We are the only one selling HIGH TF CF DA PA Blog Comments Backlinks.

I offer you to build manual 300 dofollow backlinks on High PA/DA and CF/TF page that are able to grab maximum Link juice for you. also It is help Rankings with these most powerful blog comments.

Ranking your website on Google is not easy if you don’t apply the exact method.

Provide Niche Relevant Blog commenting increase site quickly in google Ranking. You Will get Contextual Backlinks along with other powerful Links to skyrocket your website.

Key Features:

  • Actual Page High Metrics
  • TOP QUALITY Domains
  • 100% Dofollow Attribute
  • Not Use Any Automated Software
  • 100% Manual Blog comments
  • High DA PA Websites
  • 100% Satisfaction Guaranteed
  • No Spam Links
  • Unlimited Revision
  • 100% White hat SEO
  • All languages accepted
  • All sites and languages accepted
  • According to latest Google Update 2018
  • 100% Approval Rates.
  • 100% Manual & Live Links
  • 100% Google Panda & Penguin Safe
  • All Languages Acceptability
  • Detailed Excel Report on Order Completion
  • 100% Satisfactory Results

FAQ:
Q: What is the average turnaround time?
A: Turnaround time is 2 to 3 working days.

Q: Are these links permanent?

A: Yes, all links are permanent.

Q: Will you work on my new site?

A: All site accepted excluding Porn and adult oriented sites.

.

I will Provide 100 Dofollow Blog Comments Backlinks High DA Website Ranking & Link Building Service for $7

I will Provide 100 Dofollow Blog Comments Backlinks High DA Website Ranking & Link Building Service

Here is our Best SEO Service

Manual Dofollow Blog Commenting backlinks is most reliable and powerful link building method in SEO marketing. Are you looking for High Authority, Trust Flow, Citation Flow , Dofollow Blog Comments? So, we heartily welcome you to our Blog Comments service. We are the only one selling HIGH TF CF DA PA Blog Comments Backlinks.

I offer you to build manual 300 dofollow backlinks on High PA/DA and CF/TF page that are able to grab maximum Link juice for you. also It is help Rankings with these most powerful blog comments.

Ranking your website on Google is not easy if you don’t apply the exact method.

Provide Niche Relevant Blog commenting increase site quickly in google Ranking. You Will get Contextual Backlinks along with other powerful Links to skyrocket your website.

Key Features:

  • Actual Page High Metrics
  • TOP QUALITY Domains
  • 100% Dofollow Attribute
  • Not Use Any Automated Software
  • 100% Manual Blog comments
  • High DA PA Websites
  • 100% Satisfaction Guaranteed
  • No Spam Links
  • Unlimited Revision
  • 100% White hat SEO
  • All languages accepted
  • All sites and languages accepted
  • According to latest Google Update 2018
  • 100% Approval Rates.
  • 100% Manual & Live Links
  • 100% Google Panda & Penguin Safe
  • All Languages Acceptability
  • Detailed Excel Report on Order Completion
  • 100% Satisfactory Results


If you have any question about the service. feel free contact me


★★★SO PLACE THE ORDERS NOW★★★

.

” I Will ” 80 High DA Dofollow Backlinks + 10 High PR9 Social Bookmark+ Extra Bonus for $2

” I Will ” 80 High DA Dofollow Backlinks + 10 High PR9 Social Bookmark+ Extra Bonus

LEVEL 3 SELLER


Hello,

In this gig, I am offering SEO backlinks service.

As every business wants ranking. I understand how important is it to do link building to boost organic google ranking and traffic Link building also plays a great role in branding.

I will make manually permanent dofollow backlinks on DA PA sites.

My off page SEO includes:

➡️Profile Backlinks

➡️Pdf Submission

➡️Image Submission

➡️Social bookmarking

➡️Forum backlinks

➡️EDU Backlinks

➡️Blog commenting

➡️Guest Post

➡️Article submission

Why me?

➡️White hat SEO

➡️100% satisfaction

➡️24/7 support

➡️Money-back guarantee

➡️100% Manual Working.mind it ALL SEO by real humans

➡️Made according to Latest Google Update 2020

For any query, message me I will be happy to facilitate you


ORDER NOW

.